diff --git a/.golangci.yml b/.golangci.yml index b24a070ba..424345ab8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,6 +9,7 @@ run: - bindata.go - .*_mock.go - jail/doc.go + - contracts/ output: format: colored-line-number diff --git a/Makefile b/Makefile index 4d09787d6..47d2bc0b1 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,10 @@ BUILD_FLAGS ?= $(shell echo "-ldflags '\ -X github.com/status-im/status-go/params.Version=$(RELEASE_TAG) \ -X github.com/status-im/status-go/params.GitCommit=$(GIT_COMMIT) \ -X github.com/status-im/status-go/vendor/github.com/ethereum/go-ethereum/metrics.EnabledStr=$(ENABLE_METRICS)'") +BUILD_FLAGS_MOBILE ?= $(shell echo "-ldflags '\ + -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` \ + -X github.com/status-im/status-go/params.Version=$(RELEASE_TAG) \ + -X github.com/status-im/status-go/params.GitCommit=$(GIT_COMMIT)'") networkid ?= StatusChain gotest_extraflags = @@ -92,13 +96,13 @@ statusgo-cross: statusgo-android statusgo-ios statusgo-android: ##@cross-compile Build status-go for Android @echo "Building status-go for Android..." gomobile init - gomobile bind -target=android -ldflags="-s -w" $(BUILD_FLAGS) -o build/bin/statusgo.aar github.com/status-im/status-go/mobile + gomobile bind -target=android -ldflags="-s -w" $(BUILD_FLAGS_MOBILE) -o build/bin/statusgo.aar github.com/status-im/status-go/mobile @echo "Android cross compilation done in build/bin/statusgo.aar" statusgo-ios: ##@cross-compile Build status-go for iOS @echo "Building status-go for iOS..." gomobile init - gomobile bind -v -target=ios -ldflags="-s -w" $(BUILD_FLAGS) -o build/bin/Statusgo.framework github.com/status-im/status-go/mobile + gomobile bind -v -target=ios -ldflags="-s -w" $(BUILD_FLAGS_MOBILE) -o build/bin/Statusgo.framework github.com/status-im/status-go/mobile @echo "iOS framework cross compilation done in build/bin/Statusgo.framework" statusgo-xgo: xgo-install ##@cross-compile Build status-go for xgo targets diff --git a/VERSION b/VERSION index 1e7ef49af..3b316bcd3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.33.0-beta.1 +0.34.0-beta.0 diff --git a/account/accounts_test.go b/account/accounts_test.go index b5db22677..848fa381e 100644 --- a/account/accounts_test.go +++ b/account/accounts_test.go @@ -9,10 +9,11 @@ import ( "reflect" "testing" + "github.com/status-im/status-go/t/utils" + "github.com/ethereum/go-ethereum/common" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - . "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) @@ -28,10 +29,11 @@ func TestVerifyAccountPassword(t *testing.T) { defer os.RemoveAll(emptyKeyStoreDir) //nolint: errcheck // import account keys - require.NoError(t, ImportTestAccount(keyStoreDir, GetAccount1PKFile())) - require.NoError(t, ImportTestAccount(keyStoreDir, GetAccount2PKFile())) + utils.Init() + require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount1PKFile())) + require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount2PKFile())) - account1Address := gethcommon.BytesToAddress(gethcommon.FromHex(TestConfig.Account1.WalletAddress)) + account1Address := gethcommon.BytesToAddress(gethcommon.FromHex(utils.TestConfig.Account1.WalletAddress)) testCases := []struct { name string @@ -43,37 +45,37 @@ func TestVerifyAccountPassword(t *testing.T) { { "correct address, correct password (decrypt should succeed)", keyStoreDir, - TestConfig.Account1.WalletAddress, - TestConfig.Account1.Password, + utils.TestConfig.Account1.WalletAddress, + utils.TestConfig.Account1.Password, nil, }, { "correct address, correct password, non-existent key store", filepath.Join(keyStoreDir, "non-existent-folder"), - TestConfig.Account1.WalletAddress, - TestConfig.Account1.Password, + utils.TestConfig.Account1.WalletAddress, + utils.TestConfig.Account1.Password, fmt.Errorf("cannot traverse key store folder: lstat %s/non-existent-folder: no such file or directory", keyStoreDir), }, { "correct address, correct password, empty key store (pk is not there)", emptyKeyStoreDir, - TestConfig.Account1.WalletAddress, - TestConfig.Account1.Password, + utils.TestConfig.Account1.WalletAddress, + utils.TestConfig.Account1.Password, fmt.Errorf("cannot locate account for address: %s", account1Address.Hex()), }, { "wrong address, correct password", keyStoreDir, "0x79791d3e8f2daa1f7fec29649d152c0ada3cc535", - TestConfig.Account1.Password, + utils.TestConfig.Account1.Password, fmt.Errorf("cannot locate account for address: %s", "0x79791d3E8F2dAa1F7FeC29649d152c0aDA3cc535"), }, { "correct address, wrong password", keyStoreDir, - TestConfig.Account1.WalletAddress, + utils.TestConfig.Account1.WalletAddress, "wrong password", // wrong password - errors.New("could not decrypt key with given passphrase"), + errors.New("could not decrypt key with given password"), }, } for _, testCase := range testCases { @@ -101,13 +103,14 @@ func TestVerifyAccountPasswordWithAccountBeforeEIP55(t *testing.T) { defer os.RemoveAll(keyStoreDir) //nolint: errcheck // Import keys and make sure one was created before EIP55 introduction. - err = ImportTestAccount(keyStoreDir, "test-account3-before-eip55.pk") + utils.Init() + err = utils.ImportTestAccount(keyStoreDir, "test-account3-before-eip55.pk") require.NoError(t, err) accManager := NewManager() - address := gethcommon.HexToAddress(TestConfig.Account3.WalletAddress) - _, err = accManager.VerifyAccountPassword(keyStoreDir, address.Hex(), TestConfig.Account3.Password) + address := gethcommon.HexToAddress(utils.TestConfig.Account3.WalletAddress) + _, err = accManager.VerifyAccountPassword(keyStoreDir, address.Hex(), utils.TestConfig.Account3.Password) require.NoError(t, err) } @@ -226,7 +229,7 @@ func (s *ManagerTestSuite) TestSelectAccountWrongAddress() { } func (s *ManagerTestSuite) TestSelectAccountWrongPassword() { - s.testSelectAccount(common.HexToAddress(s.testAccount.chatAddress), common.HexToAddress(s.testAccount.walletAddress), "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase")) + s.testSelectAccount(common.HexToAddress(s.testAccount.chatAddress), common.HexToAddress(s.testAccount.walletAddress), "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password")) } func (s *ManagerTestSuite) testSelectAccount(chat, wallet common.Address, password string, expErr error) { @@ -314,7 +317,7 @@ func (s *ManagerTestSuite) TestAddressToDecryptedAccountWrongAddress() { } func (s *ManagerTestSuite) TestAddressToDecryptedAccountWrongPassword() { - s.testAddressToDecryptedAccount(s.walletAddress, "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase")) + s.testAddressToDecryptedAccount(s.walletAddress, "wrong", errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password")) } func (s *ManagerTestSuite) testAddressToDecryptedAccount(wallet, password string, expErr error) { diff --git a/account/keystore.go b/account/keystore.go index 40e4f8971..aab648471 100644 --- a/account/keystore.go +++ b/account/keystore.go @@ -21,5 +21,6 @@ func makeAccountManager(keydir string) (manager *accounts.Manager, err error) { if err := os.MkdirAll(keydir, 0700); err != nil { return nil, err } - return accounts.NewManager(keystore.NewKeyStore(keydir, keystore.LightScryptN, keystore.LightScryptP)), nil + config := accounts.Config{InsecureUnlockAllowed: false} + return accounts.NewManager(&config, keystore.NewKeyStore(keydir, keystore.LightScryptN, keystore.LightScryptP)), nil } diff --git a/api/backend_subs_test.go b/api/backend_subs_test.go index a776e5dd5..6e1142b5d 100644 --- a/api/backend_subs_test.go +++ b/api/backend_subs_test.go @@ -233,6 +233,8 @@ func createSubscription(t *testing.T, backend *StatusBackend, params string) str } func initNodeAndLogin(t *testing.T, backend *StatusBackend) (string, string) { + utils.Init() + config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) diff --git a/api/backend_test.go b/api/backend_test.go index 436a71b80..cf093fcc3 100644 --- a/api/backend_test.go +++ b/api/backend_test.go @@ -28,6 +28,8 @@ import ( ) func TestBackendStartNodeConcurrently(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -61,6 +63,8 @@ func TestBackendStartNodeConcurrently(t *testing.T) { } func TestBackendRestartNodeConcurrently(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -87,6 +91,8 @@ func TestBackendRestartNodeConcurrently(t *testing.T) { // TODO(adam): add concurrent tests for ResetChainData() func TestBackendGettersConcurrently(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -139,6 +145,8 @@ func TestBackendGettersConcurrently(t *testing.T) { } func TestBackendAccountsConcurrently(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -199,6 +207,8 @@ func TestBackendAccountsConcurrently(t *testing.T) { } func TestBackendInjectChatAccount(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -273,6 +283,8 @@ func TestBackendConnectionChangesToOffline(t *testing.T) { } func TestBackendCallRPCConcurrently(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -347,6 +359,8 @@ func TestAppStateChange(t *testing.T) { } func TestBlockedRPCMethods(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -385,6 +399,8 @@ func TestCallRPCWithStoppedNode(t *testing.T) { // TODO(adam): add concurrent tests for: SendTransaction func TestStartStopMultipleTimes(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -402,6 +418,8 @@ func TestStartStopMultipleTimes(t *testing.T) { } func TestSignHash(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -440,6 +458,8 @@ func TestSignHash(t *testing.T) { } func TestHashTypedData(t *testing.T) { + utils.Init() + backend := NewStatusBackend() config, err := utils.MakeTestNodeConfig(params.StatusChainNetworkID) require.NoError(t, err) @@ -486,6 +506,8 @@ func TestHashTypedData(t *testing.T) { } func TestBackendGetVerifiedAccount(t *testing.T) { + utils.Init() + password := "test" tmpdir, err := ioutil.TempDir("", "verified-account-test-") require.NoError(t, err) @@ -520,7 +542,7 @@ func TestBackendGetVerifiedAccount(t *testing.T) { require.NoError(t, err) require.NoError(t, db.SaveAccounts([]accounts.Account{{Address: address}})) key, err := backend.getVerifiedWalletAccount(address.String(), "wrong-password") - require.EqualError(t, err, "could not decrypt key with given passphrase") + require.EqualError(t, err, "could not decrypt key with given password") require.Nil(t, key) }) @@ -539,6 +561,8 @@ func TestBackendGetVerifiedAccount(t *testing.T) { } func TestLoginWithKey(t *testing.T) { + utils.Init() + b := NewStatusBackend() pkey, err := crypto.GenerateKey() require.NoError(t, err) diff --git a/cmd/statusd/main.go b/cmd/statusd/main.go index c9e1ca47e..b157a2747 100644 --- a/cmd/statusd/main.go +++ b/cmd/statusd/main.go @@ -65,7 +65,10 @@ var logger = log.New("package", "status-go/cmd/statusd") func init() { flag.Var(&configFiles, "c", "JSON configuration file(s). Multiple configuration files can be specified, and will be merged in occurrence order") +} +// nolint:gocyclo +func main() { colors := terminal.IsTerminal(int(os.Stdin.Fd())) if err := logutils.OverrideRootLog(true, "ERROR", logutils.FileOptions{}, colors); err != nil { stdlog.Fatalf("Error initializing logger: %v", err) @@ -78,10 +81,7 @@ func init() { logger.Error("Extra args in command line: %v", flag.Args()) os.Exit(1) } -} -// nolint:gocyclo -func main() { opts := []params.Option{params.WithFleet(params.FleetBeta)} if *mailserver { opts = append(opts, params.WithMailserver()) @@ -275,7 +275,7 @@ Examples: Options: ` - fmt.Fprintf(os.Stderr, usage) + fmt.Fprint(os.Stderr, usage) flag.PrintDefaults() } diff --git a/contracts/ens/README.md b/contracts/ens/README.md new file mode 100644 index 000000000..c09b47e39 --- /dev/null +++ b/contracts/ens/README.md @@ -0,0 +1,20 @@ +# Swarm ENS interface + +## Usage + +Full documentation for the Ethereum Name Service [can be found as EIP 137](https://github.com/ethereum/EIPs/issues/137). +This package offers a simple binding that streamlines the registration of arbitrary UTF8 domain names to swarm content hashes. + +## Development + +The SOL file in contract subdirectory implements the ENS root registry, a simple +first-in, first-served registrar for the root namespace, and a simple resolver contract; +they're used in tests, and can be used to deploy these contracts for your own purposes. + +The solidity source code can be found at [github.com/arachnid/ens/](https://github.com/arachnid/ens/). + +The go bindings for ENS contracts are generated using `abigen` via the go generator: + +```shell +go generate ./contracts/ens +``` diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/AbstractENS.sol b/contracts/ens/contract/AbstractENS.sol similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/AbstractENS.sol rename to contracts/ens/contract/AbstractENS.sol diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ENS.sol b/contracts/ens/contract/ENS.sol similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ENS.sol rename to contracts/ens/contract/ENS.sol diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/FIFSRegistrar.sol b/contracts/ens/contract/FIFSRegistrar.sol similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/FIFSRegistrar.sol rename to contracts/ens/contract/FIFSRegistrar.sol diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/PublicResolver.sol b/contracts/ens/contract/PublicResolver.sol similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/PublicResolver.sol rename to contracts/ens/contract/PublicResolver.sol diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ens.go b/contracts/ens/contract/ens.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ens.go rename to contracts/ens/contract/ens.go diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/fifsregistrar.go b/contracts/ens/contract/fifsregistrar.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/fifsregistrar.go rename to contracts/ens/contract/fifsregistrar.go diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/publicresolver.go b/contracts/ens/contract/publicresolver.go similarity index 100% rename from vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/publicresolver.go rename to contracts/ens/contract/publicresolver.go diff --git a/contracts/ens/ens.go b/contracts/ens/ens.go new file mode 100644 index 000000000..b40427144 --- /dev/null +++ b/contracts/ens/ens.go @@ -0,0 +1,195 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package ens + +//go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go +//go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go +//go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go + +import ( + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/status-im/status-go/contracts/ens/contract" +) + +var ( + MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b") + TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010") +) + +// ENS is the swarm domain name registry and resolver +type ENS struct { + *contract.ENSSession + contractBackend bind.ContractBackend +} + +// NewENS creates a struct exposing convenient high-level operations for interacting with +// the Ethereum Name Service. +func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) { + ens, err := contract.NewENS(contractAddr, contractBackend) + if err != nil { + return nil, err + } + return &ENS{ + &contract.ENSSession{ + Contract: ens, + TransactOpts: *transactOpts, + }, + contractBackend, + }, nil +} + +// DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar. +func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) { + // Deploy the ENS registry + ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend) + if err != nil { + return ensAddr, nil, err + } + ens, err := NewENS(transactOpts, ensAddr, contractBackend) + if err != nil { + return ensAddr, nil, err + } + // Deploy the registrar + regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{}) + if err != nil { + return ensAddr, nil, err + } + // Set the registrar as owner of the ENS root + if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil { + return ensAddr, nil, err + } + return ensAddr, ens, nil +} + +func ensParentNode(name string) (common.Hash, common.Hash) { + parts := strings.SplitN(name, ".", 2) + label := crypto.Keccak256Hash([]byte(parts[0])) + if len(parts) == 1 { + return [32]byte{}, label + } + parentNode, parentLabel := ensParentNode(parts[1]) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label +} + +func EnsNode(name string) common.Hash { + parentNode, parentLabel := ensParentNode(name) + return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) +} + +func (ens *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { + resolverAddr, err := ens.Resolver(node) + if err != nil { + return nil, err + } + resolver, err := contract.NewPublicResolver(resolverAddr, ens.contractBackend) + if err != nil { + return nil, err + } + return &contract.PublicResolverSession{ + Contract: resolver, + TransactOpts: ens.TransactOpts, + }, nil +} + +func (ens *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { + registrarAddr, err := ens.Owner(node) + if err != nil { + return nil, err + } + registrar, err := contract.NewFIFSRegistrar(registrarAddr, ens.contractBackend) + if err != nil { + return nil, err + } + return &contract.FIFSRegistrarSession{ + Contract: registrar, + TransactOpts: ens.TransactOpts, + }, nil +} + +// Resolve is a non-transactional call that returns the content hash associated with a name. +func (ens *ENS) Resolve(name string) (common.Hash, error) { + node := EnsNode(name) + + resolver, err := ens.getResolver(node) + if err != nil { + return common.Hash{}, err + } + ret, err := resolver.Content(node) + if err != nil { + return common.Hash{}, err + } + return common.BytesToHash(ret[:]), nil +} + +// Addr is a non-transactional call that returns the address associated with a name. +func (ens *ENS) Addr(name string) (common.Address, error) { + node := EnsNode(name) + + resolver, err := ens.getResolver(node) + if err != nil { + return common.Address{}, err + } + ret, err := resolver.Addr(node) + if err != nil { + return common.Address{}, err + } + return common.BytesToAddress(ret[:]), nil +} + +// SetAddress sets the address associated with a name. Only works if the caller +// owns the name, and the associated resolver implements a `setAddress` function. +func (ens *ENS) SetAddr(name string, addr common.Address) (*types.Transaction, error) { + node := EnsNode(name) + + resolver, err := ens.getResolver(node) + if err != nil { + return nil, err + } + opts := ens.TransactOpts + opts.GasLimit = 200000 + return resolver.Contract.SetAddr(&opts, node, addr) +} + +// Register registers a new domain name for the caller, making them the owner of the new name. +// Only works if the registrar for the parent domain implements the FIFS registrar protocol. +func (ens *ENS) Register(name string) (*types.Transaction, error) { + parentNode, label := ensParentNode(name) + registrar, err := ens.getRegistrar(parentNode) + if err != nil { + return nil, err + } + return registrar.Contract.Register(&ens.TransactOpts, label, ens.TransactOpts.From) +} + +// SetContentHash sets the content hash associated with a name. Only works if the caller +// owns the name, and the associated resolver implements a `setContent` function. +func (ens *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) { + node := EnsNode(name) + + resolver, err := ens.getResolver(node) + if err != nil { + return nil, err + } + opts := ens.TransactOpts + opts.GasLimit = 200000 + return resolver.Contract.SetContent(&opts, node, hash) +} diff --git a/contracts/ens/ens_test.go b/contracts/ens/ens_test.go new file mode 100644 index 000000000..641c4437f --- /dev/null +++ b/contracts/ens/ens_test.go @@ -0,0 +1,94 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package ens + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + "github.com/status-im/status-go/contracts/ens/contract" +) + +var ( + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + name = "my name on ENS" + hash = crypto.Keccak256Hash([]byte("my content")) + addr = crypto.PubkeyToAddress(key.PublicKey) + testAddr = common.HexToAddress("0x1234123412341234123412341234123412341234") +) + +func TestENS(t *testing.T) { + contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000) + transactOpts := bind.NewKeyedTransactor(key) + + ensAddr, ens, err := DeployENS(transactOpts, contractBackend) + if err != nil { + t.Fatalf("can't deploy root registry: %v", err) + } + contractBackend.Commit() + + // Set ourself as the owner of the name. + if _, err := ens.Register(name); err != nil { + t.Fatalf("can't register: %v", err) + } + contractBackend.Commit() + + // Deploy a resolver and make it responsible for the name. + resolverAddr, _, _, err := contract.DeployPublicResolver(transactOpts, contractBackend, ensAddr) + if err != nil { + t.Fatalf("can't deploy resolver: %v", err) + } + if _, err := ens.SetResolver(EnsNode(name), resolverAddr); err != nil { + t.Fatalf("can't set resolver: %v", err) + } + contractBackend.Commit() + + // Set the content hash for the name. + if _, err = ens.SetContentHash(name, hash); err != nil { + t.Fatalf("can't set content hash: %v", err) + } + contractBackend.Commit() + + // Try to resolve the name. + vhost, err := ens.Resolve(name) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if vhost != hash { + t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), vhost.Hex()) + } + + // set the address for the name + if _, err = ens.SetAddr(name, testAddr); err != nil { + t.Fatalf("can't set address: %v", err) + } + contractBackend.Commit() + + // Try to resolve the name to an address + recoveredAddr, err := ens.Addr(name) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if vhost != hash { + t.Fatalf("resolve error, expected %v, got %v", testAddr.Hex(), recoveredAddr.Hex()) + } +} diff --git a/discovery/rendezvous.go b/discovery/rendezvous.go index 0e1c37610..2a88ff588 100644 --- a/discovery/rendezvous.go +++ b/discovery/rendezvous.go @@ -208,11 +208,10 @@ func (r *Rendezvous) Discover( } else { for i := range records { n, err := enrToNode(records[i]) - log.Debug("converted enr to", "ENODE", n.String()) if err != nil { log.Warn("error converting enr record to node", "err", err) - } else { + log.Debug("converted enr to", "ENODE", n.String()) select { case found <- n: case newPeriod, ok := <-period: @@ -233,7 +232,7 @@ func (r *Rendezvous) Discover( func enrToNode(record enr.Record) (*discv5.Node, error) { var ( key enode.Secp256k1 - ip enr.IP + ip enr.IPv4 tport enr.TCP uport enr.UDP nodeID discv5.NodeID diff --git a/exportlogs/logs_test.go b/exportlogs/logs_test.go index 08dc0dfc7..0fb3aa007 100644 --- a/exportlogs/logs_test.go +++ b/exportlogs/logs_test.go @@ -12,7 +12,7 @@ func TestExportLogs(t *testing.T) { tempf, err := ioutil.TempFile("", "test-dump-logs") require.NoError(t, err) logs := "first line\nsecond line\n" - n, err := fmt.Fprintf(tempf, logs) + n, err := fmt.Fprint(tempf, logs) require.NoError(t, err) require.Equal(t, len(logs), n) response := ExportFromBaseFile(tempf.Name()) diff --git a/go.mod b/go.mod index ebfa2b740..e72fe8611 100644 --- a/go.mod +++ b/go.mod @@ -2,37 +2,49 @@ module github.com/status-im/status-go go 1.12 -require ( - github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2 - github.com/beevik/ntp v0.2.0 - github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/ethereum/go-ethereum v1.8.27 - github.com/go-playground/locales v0.12.1 // indirect - github.com/go-playground/universal-translator v0.16.0 // indirect - github.com/golang/mock v1.2.0 - github.com/leodido/go-urn v1.1.0 // indirect - github.com/lib/pq v1.0.0 - github.com/libp2p/go-libp2p-core v0.0.3 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f - github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 - github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a - github.com/status-im/doubleratchet v2.0.0+incompatible - github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed - github.com/status-im/rendezvous v1.3.0 - github.com/status-im/status-protocol-go v0.0.0-20190926081215-cc44ddb7ce44 - github.com/status-im/whisper v1.4.14 - github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467 - github.com/syndtr/goleveldb v1.0.0 - go.uber.org/zap v1.10.0 - golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 - golang.org/x/text v0.3.2 - gopkg.in/go-playground/assert.v1 v1.2.1 // indirect - gopkg.in/go-playground/validator.v9 v9.29.0 - gopkg.in/natefinch/lumberjack.v2 v2.0.0 -) - -replace github.com/ethereum/go-ethereum v1.8.27 => github.com/status-im/go-ethereum v1.8.27-status.5 +replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.4 replace github.com/NaySoftware/go-fcm => github.com/status-im/go-fcm v1.0.0-status + +require ( + github.com/NaySoftware/go-fcm v0.0.0-00010101000000-000000000000 + github.com/beevik/ntp v0.2.0 + github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 + github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/ethereum/go-ethereum v1.9.5 + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect + github.com/go-playground/locales v0.12.1 // indirect + github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/golang/mock v1.3.1 + github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 // indirect + github.com/leodido/go-urn v1.1.0 // indirect + github.com/lib/pq v1.2.0 + github.com/libp2p/go-libp2p v0.4.0 // indirect + github.com/libp2p/go-libp2p-core v0.2.3 + github.com/multiformats/go-multiaddr v0.1.1 + github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f + github.com/pborman/uuid v1.2.0 + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a + github.com/status-im/doubleratchet v2.0.0+incompatible + github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 // indirect + github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7 + github.com/status-im/rendezvous v1.3.0 + github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44 + github.com/status-im/whisper v1.4.14 + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + github.com/stretchr/testify v1.4.0 + github.com/syndtr/goleveldb v1.0.0 + github.com/tyler-smith/go-bip39 v1.0.2 // indirect + github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect + go.uber.org/zap v1.10.0 + golang.org/x/crypto v0.0.0-20191001141032-4663e185863a + golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 // indirect + golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect + golang.org/x/sys v0.0.0-20190927073244-c990c680b611 // indirect + golang.org/x/text v0.3.2 + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + gopkg.in/go-playground/validator.v9 v9.29.1 + gopkg.in/natefinch/lumberjack.v2 v2.0.0 +) diff --git a/go.sum b/go.sum index 933cbd6ec..5c2dde804 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= @@ -16,6 +17,7 @@ github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= @@ -27,44 +29,46 @@ github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0g github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708 h1:tS7jSmwRqSxTnonTRlDD1oHo6Q9YOK4xHS9/v4L56eg= github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8= github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= @@ -79,14 +83,16 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I= github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU= @@ -109,15 +115,20 @@ github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa h1:o8OuEkracbk3qH6GvlI6XpEN1HTSxkzOG42xZpfDv/s= github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= +github.com/ethereum/go-ethereum v1.8.27/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2ic= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -132,20 +143,23 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/golang-migrate/migrate/v4 v4.5.0 h1:ucd2qJu1BAKTtmjh7QlWYiq01DwlE/xXYQkOPE0ZTsI= github.com/golang-migrate/migrate/v4 v4.5.0/go.mod h1:SzAcz2l+yDJVhQC7fwiF7T2MAFPMIkigJz98klRJ4OE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -154,12 +168,14 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -169,6 +185,8 @@ github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/gyuho/goraph v0.0.0-20171001060514-a7a4454fd3eb h1:1mTTeUpJ+imP9A0eSfNnzif1pkpiEoy+ait7XiSqGNc= @@ -182,21 +200,24 @@ github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883 h1:HsZXaxH4mZRDDcxGk5m1+o3R/ofaT5YrMG+aR0altIw= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= @@ -218,20 +239,24 @@ github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s= github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2 h1:BkkpZxPVs3gIf+3Tejt8lWzuo2P29N1ChGUMEpuSJ8U= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -239,6 +264,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -248,8 +274,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= -github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= @@ -257,19 +284,31 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUTk= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= +github.com/libp2p/go-libp2p v0.4.0 h1:nV2q3fdhL80OWtPyBrsoWKcw32qC4TbbR+iGjEOMRaU= +github.com/libp2p/go-libp2p v0.4.0/go.mod h1:9EsEIf9p2UDuwtPd0DwJsAl0qXVxgAnuDGRvHbfATfI= github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= +github.com/libp2p/go-libp2p-circuit v0.1.3 h1:WsMYYaA0PwdpgJSQu12EzPYf5ypkLSTgcOsWr7DYrgI= +github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.3 h1:zXikZ5pLfebtTMeIYfcwVQ2Pae77O0FIwDquwM6AGNM= +github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A= github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= @@ -286,14 +325,22 @@ github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUje github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc= github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= @@ -301,50 +348,69 @@ github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgE github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= -github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= -github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= +github.com/libp2p/go-ws-transport v0.1.2 h1:VnxQcLfSGtqupqPpBNu8fUiCv+IN1RJ2BcVqQEM+z8E= +github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/mongodb/mongo-go-driver v0.3.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -355,20 +421,29 @@ github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.1.0 h1:gsPeMvo91XvcsNlQXgJgfjYjbsVV99bvveguUvDBpyQ= +github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY= github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f h1:hd3r+uv9DNLScbOrnlj82rBldHQf3XWmCeXAWbw8euQ= @@ -377,6 +452,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a h1:m6hB6GkmZ/suOSKZM7yx3Yt+7iZ9HNfzacCykJqgXA8= github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -393,8 +470,10 @@ github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -406,24 +485,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5 h1:tpIq60O8y0FlitOnj7aFTnaiwj7ypYnJCfOwCnApKss= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 h1:H3hCXwP92pH/hSgNrCLtjxvsKJ50sq26nICbZuoR1tQ= github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315/go.mod h1:ZbKa3zlLnhGF1dAeJtMSoNtM5LgFQnqzq8eYH3uYYkU= @@ -431,50 +513,68 @@ github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d h1:A926QrjwToaPS7gi github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d/go.mod h1:Cpq811GTlHevuU6BZxk3ObOdK8AY5gHu9QGmDak0DT4= github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a h1:yVNJFSzkEG8smsvd9udiQcMJA0MIsFvlG7ba314cu+s= github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a/go.mod h1:TPq+fcJOdGrkpZpXF4UVmFjYxH0gGqnxdgZ+OzAmvJk= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/status-im/doubleratchet v2.0.0+incompatible h1:s77lF1lDubK0RKftxN2vH8G9gwtVVp13ggWfyY4O1q4= github.com/status-im/doubleratchet v2.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU= -github.com/status-im/go-ethereum v1.8.27-status.5 h1:FS+1KwA97yWh9BtHse0BLfEWtldboSiTMA7nCavxtzc= -github.com/status-im/go-ethereum v1.8.27-status.5/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU= +github.com/status-im/go-ethereum v1.9.5-status.4 h1:F5VrxH9LmTxWl4qwQjs0TI5TgG9dVuZKqGmdwHJ0cWk= +github.com/status-im/go-ethereum v1.9.5-status.4/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU= github.com/status-im/go-fcm v1.0.0-status h1:eUNKm4ooAXdEf9/GaTYeTELna5aVMOEbzjbm2irQ0gY= github.com/status-im/go-fcm v1.0.0-status/go.mod h1:0JGzul9SfemcbTdw0mkzLR42j+BTNci5aQWlI0o/uk8= github.com/status-im/go-multiaddr-ethv4 v1.2.0 h1:OT84UsUzTCwguqCpJqkrCMiL4VZ1SvUtH9a5MsZupBk= github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo= -github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed h1:K2iga8l8OQIHnk2bBq2QsZTO2Q38YWy04xIspdITCdM= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA= +github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7 h1:gWtw0g41Y55lIOjUikkx0qjSfzl5lNZWhsvzWZIdtvQ= +github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA= github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4Lbjg4= github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s= -github.com/status-im/status-protocol-go v0.0.0-20190926081215-cc44ddb7ce44 h1:RzyVhzGT79zfFFW7RpGnfk/Nvg+WjgTamGdw4o2InYk= -github.com/status-im/status-protocol-go v0.0.0-20190926081215-cc44ddb7ce44/go.mod h1:g059a1CeUmHKzsokiKwdk5pCuhCPE1GeOh8vULbfn5w= +github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44 h1:/dyB9wnkkNURvznzewDov3ulnLbjl8h1OeEEr5NQmQM= +github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44/go.mod h1:g059a1CeUmHKzsokiKwdk5pCuhCPE1GeOh8vULbfn5w= github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc= github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467 h1:/pva5wyh0PKqe0bnHBbndEzbqsilMKFNXI0GPbO+L8c= github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/vacp2p/mvds v0.0.21 h1:YeYja8noKsHvrnOHM4pqjBvDwwy+kUzXMkX1IBYJAbU= github.com/vacp2p/mvds v0.0.21/go.mod h1:pIqr2Hg4cIkTJniGPCp4ptong2jxgxx6uToVoY94+II= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= @@ -485,14 +585,21 @@ github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= @@ -501,7 +608,7 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGqAlGX3+oCsiL1Q629FL90M= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -509,10 +616,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191001141032-4663e185863a h1:IyO+qCPGvLbq/+jPIOaTO1++UxgNrSpFnvQlL0hnMMQ= +golang.org/x/crypto v0.0.0-20191001141032-4663e185863a/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -531,14 +642,15 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6 h1:FP8hkuE6yUEaJnK7O2eTuejKWwW+Rhfj80dQ2JcKxCU= golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -550,11 +662,14 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190214214411-e77772198cdc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -562,10 +677,15 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA= golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190927073244-c990c680b611 h1:q9u40nxWT5zRClI/uU9dHCiYGottAg6Nzz4YUQyHxdA= +golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -578,10 +698,13 @@ golang.org/x/tools v0.0.0-20170215214335-be0fcc31ae23/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= @@ -609,8 +732,8 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.29.0 h1:5ofssLNYgAA/inWn6rTZ4juWpRJUwEnXc1LG2IeXwgQ= -gopkg.in/go-playground/validator.v9 v9.29.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= +gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= @@ -619,6 +742,8 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5 h1:VWXVtmkY4YFVuF1FokZ0PUsuvtx3Di6z/m47daSP5f0= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= diff --git a/lib/library_test.go b/lib/library_test.go index 7b1c31160..4d31d47c9 100644 --- a/lib/library_test.go +++ b/lib/library_test.go @@ -7,12 +7,47 @@ package main import ( + "os" + "path" + "path/filepath" + "strconv" "testing" + . "github.com/status-im/status-go/t/utils" //nolint: golint "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func TestMain(m *testing.M) { + Init() + + testChainDir = filepath.Join(TestDataDir, TestNetworkNames[GetNetworkID()]) + keystoreDir = filepath.Join(TestDataDir, TestNetworkNames[GetNetworkID()], "keystore") + + nodeConfigJSON = `{ + "NetworkId": ` + strconv.Itoa(GetNetworkID()) + `, + "DataDir": "` + testChainDir + `", + "KeyStoreDir": "` + filepath.Join(testChainDir, "keystore") + `", + "HTTPPort": ` + strconv.Itoa(TestConfig.Node.HTTPPort) + `, + "LogLevel": "INFO", + "NoDiscovery": true, + "APIModules": "web3,eth", + "LightEthConfig": { + "Enabled": true + }, + "WhisperConfig": { + "Enabled": true, + "DataDir": "` + path.Join(testChainDir, "wnode") + `", + "EnableNTPSync": false + }, + "ShhextConfig": { + "BackupDisabledDataDir": "` + testChainDir + `" + } +}` + + os.Exit(m.Run()) +} + // the actual test functions are in non-_test.go files (so that they can use cgo i.e. import "C") // the only intent of these wrappers is for gotest can find what tests are exposed. func TestExportedAPI(t *testing.T) { diff --git a/lib/library_test_utils.go b/lib/library_test_utils.go index f7f3158b5..1e75332fa 100644 --- a/lib/library_test_utils.go +++ b/lib/library_test_utils.go @@ -17,10 +17,8 @@ import ( "io/ioutil" "math/big" "os" - "path" "path/filepath" "reflect" - "strconv" "strings" "testing" "time" @@ -31,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/status-im/status-go/account" "github.com/status-im/status-go/signal" - . "github.com/status-im/status-go/t/utils" //nolint: golint "github.com/status-im/status-go/transactions" "github.com/stretchr/testify/require" @@ -99,32 +96,6 @@ func waitSignal(feed *event.Feed, event string, timeout time.Duration) error { } } -func init() { - testChainDir = filepath.Join(TestDataDir, TestNetworkNames[GetNetworkID()]) - keystoreDir = filepath.Join(TestDataDir, TestNetworkNames[GetNetworkID()], "keystore") - - nodeConfigJSON = `{ - "NetworkId": ` + strconv.Itoa(GetNetworkID()) + `, - "DataDir": "` + testChainDir + `", - "KeyStoreDir": "` + filepath.Join(testChainDir, "keystore") + `", - "HTTPPort": ` + strconv.Itoa(TestConfig.Node.HTTPPort) + `, - "LogLevel": "INFO", - "NoDiscovery": true, - "APIModules": "web3,eth", - "LightEthConfig": { - "Enabled": true - }, - "WhisperConfig": { - "Enabled": true, - "DataDir": "` + path.Join(testChainDir, "wnode") + `", - "EnableNTPSync": false - }, - "ShhextConfig": { - "BackupDisabledDataDir": "` + testChainDir + `" - } -}` -} - func createAccountAndLogin(t *testing.T, feed *event.Feed) account.Info { account1, _, err := statusBackend.AccountManager().CreateAccount(TestConfig.Account1.Password) require.NoError(t, err) @@ -321,7 +292,7 @@ func testCallRPC(t *testing.T, feed *event.Feed) bool { func testCallRPCWithPrivateAPI(t *testing.T, feed *event.Feed) bool { createAccountAndLogin(t, feed) - expected := `{"jsonrpc":"2.0","id":64,"error":{"code":-32601,"message":"The method admin_nodeInfo does not exist/is not available"}}` + expected := `{"jsonrpc":"2.0","id":64,"error":{"code":-32601,"message":"the method admin_nodeInfo does not exist/is not available"}}` rawResponse := CallRPC(C.CString(`{"jsonrpc":"2.0","method":"admin_nodeInfo","params":[],"id":64}`)) require.Equal(t, expected, C.GoString(rawResponse)) return true diff --git a/metrics/node/metrics.go b/metrics/node/metrics.go index 5a9038448..13549cbfa 100644 --- a/metrics/node/metrics.go +++ b/metrics/node/metrics.go @@ -2,7 +2,6 @@ package node import ( "errors" - "flag" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" @@ -16,32 +15,48 @@ var ( ) func init() { - // When running tests, we want metrics to be enabled. - // Having init() in metrics_test.go does not work because - // this init() is executed first. - if flag.Lookup("test.v") != nil { - metrics.Enabled = true - } - nodePeersCounter = metrics.NewRegisteredCounter("p2p/Peers", nil) nodePeersGauge = metrics.NewRegisteredGauge("p2p/PeersAbsolute", nil) nodeMaxPeersGauge = metrics.NewRegisteredGauge("p2p/MaxPeers", nil) } func updateNodeMetrics(node *node.Node, evType p2p.PeerEventType) error { - server := node.Server() - if server == nil { - return errors.New("p2p server is unavailable") + change, err := computeMetrics(node, evType) + if err != nil { + return err } - if evType == p2p.PeerEventTypeAdd { - nodePeersCounter.Inc(1) - } else if evType == p2p.PeerEventTypeDrop { - nodePeersCounter.Dec(1) + if change.Counter > 0 { + nodePeersCounter.Inc(change.Counter) + } else if change.Counter < 0 { + nodePeersCounter.Dec(change.Counter) } - nodePeersGauge.Update(int64(server.PeerCount())) - nodeMaxPeersGauge.Update(int64(server.MaxPeers)) + nodePeersGauge.Update(change.Absolute) + nodeMaxPeersGauge.Update(change.Max) return nil } + +type peersChange struct { + Counter int64 + Absolute int64 + Max int64 +} + +func computeMetrics(node *node.Node, evType p2p.PeerEventType) (result peersChange, err error) { + server := node.Server() + if server == nil { + return result, errors.New("p2p server is unavailable") + } + + if evType == p2p.PeerEventTypeAdd { + result.Counter = 1 + } else if evType == p2p.PeerEventTypeDrop { + result.Counter = -1 + } + + result.Absolute = int64(server.PeerCount()) + result.Max = int64(server.MaxPeers) + return +} diff --git a/metrics/node/metrics_test.go b/metrics/node/metrics_test.go index 00383b267..88fb5b04d 100644 --- a/metrics/node/metrics_test.go +++ b/metrics/node/metrics_test.go @@ -21,28 +21,25 @@ func TestUpdateNodeMetricsPeersCounter(t *testing.T) { require.NoError(t, n.Start()) defer func() { require.NoError(t, n.Stop()) }() - err = updateNodeMetrics(n, p2p.PeerEventTypeAdd) + change, err := computeMetrics(n, p2p.PeerEventTypeAdd) require.NoError(t, err) - require.Equal(t, int64(1), nodePeersCounter.Count()) - require.Equal(t, int64(10), nodeMaxPeersGauge.Value()) - - err = updateNodeMetrics(n, p2p.PeerEventTypeAdd) - require.NoError(t, err) - require.Equal(t, int64(2), nodePeersCounter.Count()) + require.Equal(t, int64(1), change.Counter) + require.Equal(t, int64(10), change.Max) // skip other events - err = updateNodeMetrics(n, p2p.PeerEventTypeMsgRecv) + change, err = computeMetrics(n, p2p.PeerEventTypeMsgRecv) require.NoError(t, err) - err = updateNodeMetrics(n, p2p.PeerEventTypeMsgSend) + require.Equal(t, int64(0), change.Counter) + change, err = computeMetrics(n, p2p.PeerEventTypeMsgSend) require.NoError(t, err) - require.Equal(t, int64(2), nodePeersCounter.Count()) + require.Equal(t, int64(0), change.Counter) - err = updateNodeMetrics(n, p2p.PeerEventTypeDrop) + change, err = computeMetrics(n, p2p.PeerEventTypeDrop) require.NoError(t, err) - require.Equal(t, int64(1), nodePeersCounter.Count()) + require.Equal(t, int64(-1), change.Counter) n.Server().MaxPeers = 20 - err = updateNodeMetrics(n, p2p.PeerEventTypeDrop) + change, err = computeMetrics(n, p2p.PeerEventTypeDrop) require.NoError(t, err) - require.Equal(t, int64(20), nodeMaxPeersGauge.Value()) + require.Equal(t, int64(20), change.Max) } diff --git a/node/node.go b/node/node.go index 143e720f5..642446d2e 100644 --- a/node/node.go +++ b/node/node.go @@ -246,10 +246,6 @@ func activateLightEthService(stack *node.Node, accs *accounts.Manager, config *p ethConf.SyncMode = downloader.LightSync ethConf.NetworkId = config.NetworkID ethConf.DatabaseCache = config.LightEthConfig.DatabaseCache - ethConf.ULC = ð.ULCConfig{ - TrustedServers: config.LightEthConfig.TrustedNodes, - MinTrustedFraction: config.LightEthConfig.MinTrustedFraction, - } return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { // NOTE(dshulyak) here we set our instance of the accounts manager. // without sharing same instance selected account won't be visible for personal_* methods. diff --git a/node/node_test.go b/node/node_test.go index c8fcb6640..af8aae581 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/status-im/status-go/params" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/require" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/storage" @@ -18,7 +18,8 @@ var enode1 = "enode://f32efef2739e5135a0f9a80600b321ba4d13393a5f1d3f5f593df85919 var enode2 = "enode://f32efef2739e5135a0f9a80600b321ba4d13393a5f1d3f5f593df85919262f06c70bfa66d38507b9d79a91021f5e200ec20150592e72934c66248e87014c4317@1.1.1.1:30404" func TestMakeNodeDefaultConfig(t *testing.T) { - config, err := MakeTestNodeConfig(3) + utils.Init() + config, err := utils.MakeTestNodeConfig(3) require.NoError(t, err) db, err := leveldb.Open(storage.NewMemStorage(), nil) @@ -29,7 +30,8 @@ func TestMakeNodeDefaultConfig(t *testing.T) { } func TestMakeNodeWellFormedBootnodes(t *testing.T) { - config, err := MakeTestNodeConfig(3) + utils.Init() + config, err := utils.MakeTestNodeConfig(3) require.NoError(t, err) bootnodes := []string{ @@ -46,7 +48,8 @@ func TestMakeNodeWellFormedBootnodes(t *testing.T) { } func TestMakeNodeMalformedBootnodes(t *testing.T) { - config, err := MakeTestNodeConfig(3) + utils.Init() + config, err := utils.MakeTestNodeConfig(3) require.NoError(t, err) bootnodes := []string{ diff --git a/node/status_node_rpc_client_test.go b/node/status_node_rpc_client_test.go index b29c2803d..38d8cec71 100644 --- a/node/status_node_rpc_client_test.go +++ b/node/status_node_rpc_client_test.go @@ -85,7 +85,7 @@ func TestNodeRPCClientCallOnlyPublicAPIs(t *testing.T) { // call private API with public RPC client err = client.Call(&result, "pri_someMethod") - require.EqualError(t, err, "The method pri_someMethod does not exist/is not available") + require.EqualError(t, err, "the method pri_someMethod does not exist/is not available") } func TestNodeRPCClientCallWhitelistedPrivateService(t *testing.T) { diff --git a/node/status_node_test.go b/node/status_node_test.go index 9fd879cda..55ca5b64f 100644 --- a/node/status_node_test.go +++ b/node/status_node_test.go @@ -161,7 +161,7 @@ func TestStatusNodeAddPeer(t *testing.T) { require.NoError(t, err) require.NoError(t, peer.Start()) defer func() { require.NoError(t, peer.Stop()) }() - peerURL := peer.Server().Self().String() + peerURL := peer.Server().Self().URLv4() n := New() @@ -200,7 +200,7 @@ func TestStatusNodeReconnectStaticPeers(t *testing.T) { var errCh <-chan error - peerURL := peer.Server().Self().String() + peerURL := peer.Server().Self().URLv4() n := New() // checks before node is started diff --git a/peers/peerpool_test.go b/peers/peerpool_test.go index 337f4c4a7..3125f88c9 100644 --- a/peers/peerpool_test.go +++ b/peers/peerpool_test.go @@ -182,6 +182,7 @@ func (s *PeerPoolSimulationSuite) TestSingleTopicDiscoveryWithFailoverEthV5() { } func (s *PeerPoolSimulationSuite) TestSingleTopicDiscoveryWithFailoverRendezvous() { + s.T().Skip("Skipping due to being flaky") s.setupRendezvous() s.singleTopicDiscoveryWithFailover() } diff --git a/peers/topicpool_test.go b/peers/topicpool_test.go index 1f38ed1a3..73b9ffa3b 100644 --- a/peers/topicpool_test.go +++ b/peers/topicpool_test.go @@ -430,7 +430,7 @@ func TestServerIgnoresInboundPeer(t *testing.T) { require.Contains(t, topicPool.pendingPeers, clientID) require.False(t, topicPool.pendingPeers[clientID].added) - errch := helpers.WaitForPeerAsync(server, client.Self().String(), p2p.PeerEventTypeAdd, 5*time.Second) + errch := helpers.WaitForPeerAsync(server, client.Self().URLv4(), p2p.PeerEventTypeAdd, 5*time.Second) // connect to a server from client. client will be an inbound connection for a server. client.AddPeer(server.Self()) select { @@ -441,7 +441,7 @@ func TestServerIgnoresInboundPeer(t *testing.T) { } // wait some time to confirm that RemovePeer wasn't called on the server object. - errch = helpers.WaitForPeerAsync(server, client.Self().String(), p2p.PeerEventTypeDrop, time.Second) + errch = helpers.WaitForPeerAsync(server, client.Self().URLv4(), p2p.PeerEventTypeDrop, time.Second) // simulate that event was received by a topic pool. // topic pool will ignore this even because it sees that it is inbound connection. topicPool.ConfirmAdded(server, clientID) diff --git a/services/shhext/mailservers/connmanager.go b/services/shhext/mailservers/connmanager.go index 4970dde10..84c58ff4a 100644 --- a/services/shhext/mailservers/connmanager.go +++ b/services/shhext/mailservers/connmanager.go @@ -195,9 +195,7 @@ func (state *internalState) ReachedTarget() bool { func (state *internalState) replaceNodes(new map[enode.ID]*enode.Node) { for nid, n := range state.currentNodes { if _, exist := new[nid]; !exist { - if _, exist := state.connected[nid]; exist { - delete(state.connected, nid) - } + delete(state.connected, nid) state.srv.RemovePeer(n) } } diff --git a/services/shhext/service_test.go b/services/shhext/service_test.go index ed55c7f74..8f66e9b86 100644 --- a/services/shhext/service_test.go +++ b/services/shhext/service_test.go @@ -249,27 +249,27 @@ func (s *ShhExtSuite) TestRequestMessagesErrors() { } func (s *ShhExtSuite) TestMultipleRequestMessagesWithoutForce() { - waitErr := helpers.WaitForPeerAsync(s.nodes[0].Server(), s.nodes[1].Server().Self().String(), p2p.PeerEventTypeAdd, time.Second) + waitErr := helpers.WaitForPeerAsync(s.nodes[0].Server(), s.nodes[1].Server().Self().URLv4(), p2p.PeerEventTypeAdd, time.Second) s.nodes[0].Server().AddPeer(s.nodes[1].Server().Self()) s.Require().NoError(<-waitErr) client, err := s.nodes[0].Attach() s.NoError(err) s.NoError(client.Call(nil, "shhext_requestMessages", MessagesRequest{ - MailServerPeer: s.nodes[1].Server().Self().String(), + MailServerPeer: s.nodes[1].Server().Self().URLv4(), Topics: []whisper.TopicType{{1}}, })) s.EqualError(client.Call(nil, "shhext_requestMessages", MessagesRequest{ - MailServerPeer: s.nodes[1].Server().Self().String(), + MailServerPeer: s.nodes[1].Server().Self().URLv4(), Topics: []whisper.TopicType{{1}}, }), "another request with the same topics was sent less than 3s ago. Please wait for a bit longer, or set `force` to true in request parameters") s.NoError(client.Call(nil, "shhext_requestMessages", MessagesRequest{ - MailServerPeer: s.nodes[1].Server().Self().String(), + MailServerPeer: s.nodes[1].Server().Self().URLv4(), Topics: []whisper.TopicType{{2}}, })) } func (s *ShhExtSuite) TestFailedRequestUnregistered() { - waitErr := helpers.WaitForPeerAsync(s.nodes[0].Server(), s.nodes[1].Server().Self().String(), p2p.PeerEventTypeAdd, time.Second) + waitErr := helpers.WaitForPeerAsync(s.nodes[0].Server(), s.nodes[1].Server().Self().URLv4(), p2p.PeerEventTypeAdd, time.Second) s.nodes[0].Server().AddPeer(s.nodes[1].Server().Self()) s.Require().NoError(<-waitErr) client, err := s.nodes[0].Attach() @@ -280,7 +280,7 @@ func (s *ShhExtSuite) TestFailedRequestUnregistered() { Topics: topics, }), "Could not find peer with ID: 10841e6db5c02fc331bf36a8d2a9137a1696d9d3b6b1f872f780e02aa8ec5bba") s.NoError(client.Call(nil, "shhext_requestMessages", MessagesRequest{ - MailServerPeer: s.nodes[1].Server().Self().String(), + MailServerPeer: s.nodes[1].Server().Self().URLv4(), Topics: topics, })) } @@ -346,7 +346,7 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() { defer func() { s.NoError(mailNode.Stop()) }() // add mailPeer as a peer - waitErr := helpers.WaitForPeerAsync(aNode.Server(), mailNode.Server().Self().String(), p2p.PeerEventTypeAdd, time.Second) + waitErr := helpers.WaitForPeerAsync(aNode.Server(), mailNode.Server().Self().URLv4(), p2p.PeerEventTypeAdd, time.Second) aNode.Server().AddPeer(mailNode.Server().Self()) s.Require().NoError(<-waitErr) @@ -356,7 +356,7 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() { symKeyID, symKeyErr := shh.AddSymKeyFromPassword("some-pass") s.Require().NoError(symKeyErr) hash, err = api.RequestMessages(context.TODO(), MessagesRequest{ - MailServerPeer: mailNode.Server().Self().String(), + MailServerPeer: mailNode.Server().Self().URLv4(), SymKeyID: symKeyID, Force: true, }) @@ -365,7 +365,7 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() { // Send a request without a symmetric key. In this case, // a public key extracted from MailServerPeer will be used. hash, err = api.RequestMessages(context.TODO(), MessagesRequest{ - MailServerPeer: mailNode.Server().Self().String(), + MailServerPeer: mailNode.Server().Self().URLv4(), Force: true, }) s.Require().NoError(err) diff --git a/services/wallet/service_test.go b/services/wallet/service_test.go index 962c0b4b6..b0540d471 100644 --- a/services/wallet/service_test.go +++ b/services/wallet/service_test.go @@ -19,6 +19,7 @@ import ( ) func TestReactorChanges(t *testing.T) { + utils.Init() suite.Run(t, new(ReactorChangesSuite)) } diff --git a/t/devtests/miner/node.go b/t/devtests/miner/node.go index e47068958..cbdfbdd80 100644 --- a/t/devtests/miner/node.go +++ b/t/devtests/miner/node.go @@ -56,8 +56,6 @@ func NewDevNode(faucet common.Address) (*node.Node, error) { extra = append(extra, acc.Address[:]...) extra = append(extra, make([]byte, 65)...) // extraSeal ethcfg.Genesis.ExtraData = extra - ethcfg.MinerGasPrice = big.NewInt(1) - ethcfg.Etherbase = acc.Address return stack, stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ðcfg) diff --git a/t/e2e/accounts/accounts_test.go b/t/e2e/accounts/accounts_test.go index 2b1746517..090c07183 100644 --- a/t/e2e/accounts/accounts_test.go +++ b/t/e2e/accounts/accounts_test.go @@ -10,8 +10,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/status-im/status-go/account" "github.com/status-im/status-go/extkeys" - e2e "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/e2e" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" ) @@ -25,6 +25,7 @@ func buildLoginParams(mainAccountAddress, chatAddress, password string, watchAdd } func TestAccountsTestSuite(t *testing.T) { + utils.Init() suite.Run(t, new(AccountsTestSuite)) } @@ -43,7 +44,7 @@ func (s *AccountsTestSuite) TestAccountsList() { s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)") // create an account - accountInfo, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) // ensure that there is still no accounts returned @@ -52,7 +53,14 @@ func (s *AccountsTestSuite) TestAccountsList() { s.Zero(len(accounts), "accounts returned, while there should be none (we haven't logged in yet)") // select account (sub-accounts will be created for this key) - err = s.Backend.SelectAccount(buildLoginParams(accountInfo.WalletAddress, accountInfo.ChatAddress, TestConfig.Account1.Password, nil)) + err = s.Backend.SelectAccount( + buildLoginParams( + accountInfo.WalletAddress, + accountInfo.ChatAddress, + utils.TestConfig.Account1.Password, + nil, + ), + ) s.NoError(err, "account selection failed") // at this point main account should show up @@ -121,13 +129,13 @@ func (s *AccountsTestSuite) TestRecoverAccount() { s.NotNil(keyStore) // create an acc - accountInfo, mnemonic, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo, mnemonic, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s, mnemonic:%s}", accountInfo.WalletAddress, accountInfo.WalletPubKey, accountInfo.ChatAddress, accountInfo.ChatPubKey, mnemonic) // try recovering using password + mnemonic - accountInfoCheck, err := s.Backend.AccountManager().RecoverAccount(TestConfig.Account1.Password, mnemonic) + accountInfoCheck, err := s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) s.NoError(err, "recover acc failed") s.EqualValues(accountInfo, accountInfoCheck, "incorrect accound details recovered") @@ -136,23 +144,23 @@ func (s *AccountsTestSuite) TestRecoverAccount() { acc, err := account.ParseAccountString(accountInfo.WalletAddress) s.NoError(err, "can not get acc from address") - acc, key, err := keyStore.AccountDecryptedKey(acc, TestConfig.Account1.Password) + acc, key, err := keyStore.AccountDecryptedKey(acc, utils.TestConfig.Account1.Password) s.NoError(err, "can not obtain decrypted acc key") extChild2String := key.ExtendedKey.String() - s.NoError(keyStore.Delete(acc, TestConfig.Account1.Password), "cannot remove acc") + s.NoError(keyStore.Delete(acc, utils.TestConfig.Account1.Password), "cannot remove acc") - accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(TestConfig.Account1.Password, mnemonic) + accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) s.NoError(err, "recover acc failed (for non-cached acc)") s.EqualValues(accountInfo, accountInfoCheck, "incorrect acc details recovered (for non-cached acc)") // make sure that extended key exists and is imported ok too - _, key, err = keyStore.AccountDecryptedKey(acc, TestConfig.Account1.Password) + _, key, err = keyStore.AccountDecryptedKey(acc, utils.TestConfig.Account1.Password) s.NoError(err) s.Equal(extChild2String, key.ExtendedKey.String(), "CKD#2 key mismatch") // make sure that calling import several times, just returns from cache (no error is expected) - accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(TestConfig.Account1.Password, mnemonic) + accountInfoCheck, err = s.Backend.AccountManager().RecoverAccount(utils.TestConfig.Account1.Password, mnemonic) s.NoError(err, "recover acc failed (for non-cached acc)") s.EqualValues(accountInfo, accountInfoCheck, "incorrect acc details recovered (for non-cached acc)") } @@ -162,26 +170,26 @@ func (s *AccountsTestSuite) TestSelectAccount() { defer s.StopTestBackend() // create an account - accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", accountInfo1.WalletAddress, accountInfo1.WalletPubKey, accountInfo1.ChatAddress, accountInfo1.ChatPubKey) - accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) s.T().Logf("Account created: {walletAddress: %s, walletKey: %s, chatAddress: %s, chatKey: %s}", accountInfo2.WalletAddress, accountInfo2.WalletPubKey, accountInfo2.ChatAddress, accountInfo2.ChatPubKey) // try selecting with wrong password err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword", nil)) - expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") + expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password") s.EqualError(expectedErr, err.Error(), "select account is expected to throw error: wrong password used") - err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, TestConfig.Account1.Password, nil)) + err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, utils.TestConfig.Account1.Password, nil)) s.NoError(err) // select another account, make sure that previous account is wiped out from Whisper cache - s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, TestConfig.Account1.Password, nil))) + s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, utils.TestConfig.Account1.Password, nil))) } func (s *AccountsTestSuite) TestSetChatAccount() { @@ -208,9 +216,9 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { s.StartTestBackend() // create test accounts - accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo1, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) - accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) + accountInfo2, _, err := s.Backend.AccountManager().CreateAccount(utils.TestConfig.Account1.Password) s.NoError(err) // make sure that no account is selected by default @@ -223,14 +231,14 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { // select account err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword", nil)) - expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") + expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password") s.EqualError(expectedErr, err.Error()) watchAddresses := []common.Address{ common.HexToAddress("0x00000000000000000000000000000000000001"), common.HexToAddress("0x00000000000000000000000000000000000002"), } - s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, TestConfig.Account1.Password, watchAddresses))) + s.NoError(s.Backend.SelectAccount(buildLoginParams(accountInfo2.WalletAddress, accountInfo2.ChatAddress, utils.TestConfig.Account1.Password, watchAddresses))) // stop node (and all of its sub-protocols) nodeConfig := s.Backend.StatusNode().Config() diff --git a/t/e2e/api/api_test.go b/t/e2e/api/api_test.go index fd2e7a8d7..d3ebffa5f 100644 --- a/t/e2e/api/api_test.go +++ b/t/e2e/api/api_test.go @@ -10,13 +10,14 @@ import ( "github.com/status-im/status-go/node" "github.com/status-im/status-go/params" "github.com/status-im/status-go/signal" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/storage" ) func TestAPI(t *testing.T) { + utils.Init() suite.Run(t, new(APITestSuite)) } @@ -45,10 +46,10 @@ func (s *APITestSuite) TestRaceConditions() { progress := make(chan struct{}, cnt) rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - nodeConfig1, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig1, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.NoError(err) - nodeConfig2, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig2, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.NoError(err) nodeConfigs := []*params.NodeConfig{nodeConfig1, nodeConfig2} @@ -123,7 +124,7 @@ func (s *APITestSuite) TestEventsNodeStartStop() { envelopes <- envelope }) - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.NoError(err) s.NoError(s.backend.AccountManager().InitKeystore(nodeConfig.KeyStoreDir)) s.Require().NoError(s.backend.StartNode(nodeConfig)) @@ -162,7 +163,7 @@ func (s *APITestSuite) TestNodeStartCrash() { }) defer signal.ResetDefaultNodeNotificationHandler() - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.NoError(err) db, err := leveldb.Open(storage.NewMemStorage(), nil) diff --git a/t/e2e/api/backend_test.go b/t/e2e/api/backend_test.go index 4c65c93a7..a01f6c534 100644 --- a/t/e2e/api/backend_test.go +++ b/t/e2e/api/backend_test.go @@ -12,6 +12,7 @@ import ( ) func TestAPIBackendTestSuite(t *testing.T) { + Init() // from t/utils suite.Run(t, new(APIBackendTestSuite)) } diff --git a/t/e2e/node/manager_test.go b/t/e2e/node/manager_test.go index 1c47c2946..9ee0a55cf 100644 --- a/t/e2e/node/manager_test.go +++ b/t/e2e/node/manager_test.go @@ -18,6 +18,7 @@ import ( ) func TestManagerTestSuite(t *testing.T) { + e2e.Init() suite.Run(t, new(ManagerTestSuite)) } diff --git a/t/e2e/rpc/client_test.go b/t/e2e/rpc/client_test.go index 3ba41ec8d..96ff11f91 100644 --- a/t/e2e/rpc/client_test.go +++ b/t/e2e/rpc/client_test.go @@ -15,6 +15,7 @@ type RPCClientTestSuite struct { } func TestRPCClientTestSuite(t *testing.T) { + e2e.Init() suite.Run(t, new(RPCClientTestSuite)) } diff --git a/t/e2e/rpc/rpc_test.go b/t/e2e/rpc/rpc_test.go index b6e13504c..11f197369 100644 --- a/t/e2e/rpc/rpc_test.go +++ b/t/e2e/rpc/rpc_test.go @@ -17,6 +17,7 @@ import ( ) func TestRPCTestSuite(t *testing.T) { + e2e.Init() suite.Run(t, new(RPCTestSuite)) } diff --git a/t/e2e/services/filters_latest_test.go b/t/e2e/services/filters_latest_test.go index 32c2e94d2..9a071a575 100644 --- a/t/e2e/services/filters_latest_test.go +++ b/t/e2e/services/filters_latest_test.go @@ -7,22 +7,23 @@ import ( "time" "github.com/status-im/status-go/params" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" - - . "github.com/status-im/status-go/t/utils" ) func TestFiltersAPISuite(t *testing.T) { + utils.Init() s := new(FiltersAPISuite) s.upstream = false suite.Run(t, s) } func TestFiltersAPISuiteUpstream(t *testing.T) { + utils.Init() s := new(FiltersAPISuite) s.upstream = true - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { + if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { t.Skip() return } @@ -50,8 +51,7 @@ func (s *FiltersAPISuite) TestFilters() { filterID := s.filterIDFromRPCResponse(response) // we don't check new blocks on private network, because no one mines them - if GetNetworkID() != params.StatusChainNetworkID { - + if utils.GetNetworkID() != params.StatusChainNetworkID { timeout := time.After(time.Minute) newBlocksChannel := s.getFirstFilterChange(filterID) @@ -61,7 +61,6 @@ func (s *FiltersAPISuite) TestFilters() { case <-timeout: s.Fail("timeout while waiting for filter results") } - } basicCall = fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_uninstallFilter","params":["%s"],"id":67}`, filterID) diff --git a/t/e2e/services/peer_api_test.go b/t/e2e/services/peer_api_test.go index 09f0ea19a..1eec55c46 100644 --- a/t/e2e/services/peer_api_test.go +++ b/t/e2e/services/peer_api_test.go @@ -4,18 +4,19 @@ import ( "testing" "github.com/status-im/status-go/params" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" - - . "github.com/status-im/status-go/t/utils" ) func TestPeerAPISuite(t *testing.T) { + utils.Init() s := new(PeerAPISuite) s.upstream = false suite.Run(t, s) } func TestPeerAPISuiteUpstream(t *testing.T) { + utils.Init() s := new(PeerAPISuite) s.upstream = true suite.Run(t, s) @@ -27,7 +28,7 @@ type PeerAPISuite struct { } func (s *PeerAPISuite) TestAccessiblePeerAPIs() { - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { + if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { s.T().Skip() return } diff --git a/t/e2e/services/status_api_test.go b/t/e2e/services/status_api_test.go index 582efe63b..92bebf194 100644 --- a/t/e2e/services/status_api_test.go +++ b/t/e2e/services/status_api_test.go @@ -9,7 +9,7 @@ import ( "github.com/status-im/status-go/account" "github.com/status-im/status-go/params" "github.com/status-im/status-go/services/status" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" ) @@ -22,12 +22,14 @@ type statusTestParams struct { } func TestStatusAPISuite(t *testing.T) { + utils.Init() s := new(StatusAPISuite) s.upstream = false suite.Run(t, s) } func TestStatusAPISuiteUpstream(t *testing.T) { + utils.Init() s := new(StatusAPISuite) s.upstream = true suite.Run(t, s) @@ -39,7 +41,7 @@ type StatusAPISuite struct { } func (s *StatusAPISuite) TestAccessibleStatusAPIs() { - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { + if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { s.T().Skip() return } @@ -61,8 +63,8 @@ func (s *StatusAPISuite) TestAccessibleStatusAPIs() { func (s *StatusAPISuite) TestStatusLoginSuccess() { addressKeyID := s.testStatusLogin(statusTestParams{ - Address: TestConfig.Account1.WalletAddress, - Password: TestConfig.Account1.Password, + Address: utils.TestConfig.Account1.WalletAddress, + Password: utils.TestConfig.Account1.Password, }) s.NotEmpty(addressKeyID) } @@ -70,7 +72,7 @@ func (s *StatusAPISuite) TestStatusLoginSuccess() { func (s *StatusAPISuite) TestStatusLoginInvalidAddress() { s.testStatusLogin(statusTestParams{ Address: "invalidaccount", - Password: TestConfig.Account1.Password, + Password: utils.TestConfig.Account1.Password, ExpectedError: account.ErrAddressToAccountMappingFailure, }) } @@ -78,7 +80,7 @@ func (s *StatusAPISuite) TestStatusLoginInvalidAddress() { func (s *StatusAPISuite) TestStatusLoginInvalidPassword() { s.testStatusLogin(statusTestParams{ Address: "invalidaccount", - Password: TestConfig.Account1.Password, + Password: utils.TestConfig.Account1.Password, ExpectedError: account.ErrAddressToAccountMappingFailure, }) } @@ -102,7 +104,7 @@ func (s *StatusAPISuite) TestStatusSignupSuccess() { func (s *StatusAPISuite) testStatusLogin(testParams statusTestParams) *status.LoginResponse { // Test upstream if that's not StatusChain - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { + if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { s.T().Skip() return nil } @@ -143,7 +145,7 @@ func (s *StatusAPISuite) testStatusLogin(testParams statusTestParams) *status.Lo func (s *StatusAPISuite) testStatusSignup(testParams statusTestParams) *status.SignupResponse { // Test upstream if that's not StatusChain - if s.upstream && GetNetworkID() == params.StatusChainNetworkID { + if s.upstream && utils.GetNetworkID() == params.StatusChainNetworkID { s.T().Skip() return nil } diff --git a/t/e2e/suites.go b/t/e2e/suites.go index 32c68d611..4ae1062b9 100644 --- a/t/e2e/suites.go +++ b/t/e2e/suites.go @@ -10,7 +10,7 @@ import ( "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/node" "github.com/status-im/status-go/signal" - . "github.com/status-im/status-go/t/utils" //nolint: golint + "github.com/status-im/status-go/t/utils" "github.com/status-im/status-go/transactions" "github.com/stretchr/testify/suite" ) @@ -24,9 +24,10 @@ type StatusNodeTestSuite struct { // All general log messages in this package should be routed through this logger. var logger = log.New("package", "status-go/t/e2e") -func init() { - for id := range TestNetworkNames { - nodeConfig, err := MakeTestNodeConfig(id) +func Init() { + utils.Init() + for id := range utils.TestNetworkNames { + nodeConfig, err := utils.MakeTestNodeConfig(id) if err != nil { panic(err) } @@ -41,7 +42,7 @@ func init() { // StartTestNode initiazes a StatusNode instances with configuration retrieved // from the test config. func (s *StatusNodeTestSuite) StartTestNode(opts ...TestNodeOption) { - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.NoError(err) // Apply any options altering node config. @@ -85,7 +86,7 @@ func (s *BackendTestSuite) TearDownTest() { // StartTestBackend imports some keys and starts a node. func (s *BackendTestSuite) StartTestBackend(opts ...TestNodeOption) { - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.Require().NoError(err) // Apply any options altering node config. @@ -103,7 +104,7 @@ func (s *BackendTestSuite) StartTestBackend(opts ...TestNodeOption) { } func (s *BackendTestSuite) StartTestBackendWithAccount(account multiaccounts.Account, password string, subaccs []accounts.Account, opts ...TestNodeOption) { - nodeConfig, err := MakeTestNodeConfig(GetNetworkID()) + nodeConfig, err := utils.MakeTestNodeConfig(utils.GetNetworkID()) s.Require().NoError(err) // Apply any options altering node config. @@ -155,10 +156,10 @@ func (s *BackendTestSuite) Transactor() *transactions.Transactor { func importTestAccounts(keyStoreDir string) (err error) { logger.Debug("Import accounts to", "dir", keyStoreDir) - err = ImportTestAccount(keyStoreDir, GetAccount1PKFile()) + err = utils.ImportTestAccount(keyStoreDir, utils.GetAccount1PKFile()) if err != nil { return } - return ImportTestAccount(keyStoreDir, GetAccount2PKFile()) + return utils.ImportTestAccount(keyStoreDir, utils.GetAccount2PKFile()) } diff --git a/t/e2e/transactions/transactions_test.go b/t/e2e/transactions/transactions_test.go index 8fbf366a6..f441bd662 100644 --- a/t/e2e/transactions/transactions_test.go +++ b/t/e2e/transactions/transactions_test.go @@ -14,8 +14,8 @@ import ( "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/params" - e2e "github.com/status-im/status-go/t/e2e" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/e2e" + "github.com/status-im/status-go/t/utils" "github.com/status-im/status-go/transactions" "github.com/stretchr/testify/suite" ) @@ -31,6 +31,7 @@ func buildLoginParams(mainAccountAddress, chatAddress, password string) account. } func TestTransactionsTestSuite(t *testing.T) { + utils.Init() suite.Run(t, new(TransactionsTestSuite)) } @@ -39,19 +40,19 @@ type TransactionsTestSuite struct { } func (s *TransactionsTestSuite) TestCallRPCSendTransaction() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) s.StartTestBackend() defer s.StopTestBackend() - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) + utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) s.sendTransactionUsingRPCClient(s.Backend.CallRPC) } func (s *TransactionsTestSuite) TestCallUpstreamRPCSendTransaction() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) - addr, err := GetRemoteURL() + addr, err := utils.GetRemoteURL() s.NoError(err) s.StartTestBackend(e2e.WithUpstream(addr)) defer s.StopTestBackend() @@ -60,19 +61,19 @@ func (s *TransactionsTestSuite) TestCallUpstreamRPCSendTransaction() { } func (s *TransactionsTestSuite) TestCallPrivateRPCSendTransaction() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) s.StartTestBackend() defer s.StopTestBackend() - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) + utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) s.sendTransactionUsingRPCClient(s.Backend.CallPrivateRPC) } func (s *TransactionsTestSuite) TestCallUpstreamPrivateRPCSendTransaction() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) - addr, err := GetRemoteURL() + addr, err := utils.GetRemoteURL() s.NoError(err) s.StartTestBackend(e2e.WithUpstream(addr)) defer s.StopTestBackend() @@ -83,7 +84,11 @@ func (s *TransactionsTestSuite) TestCallUpstreamPrivateRPCSendTransaction() { func (s *TransactionsTestSuite) sendTransactionUsingRPCClient( callRPCFn func(string) (string, error), ) { - err := s.Backend.SelectAccount(buildLoginParams(TestConfig.Account1.WalletAddress, TestConfig.Account1.ChatAddress, TestConfig.Account1.Password)) + err := s.Backend.SelectAccount(buildLoginParams( + utils.TestConfig.Account1.WalletAddress, + utils.TestConfig.Account1.ChatAddress, + utils.TestConfig.Account1.Password, + )) s.NoError(err) result, err := callRPCFn(`{ @@ -91,7 +96,7 @@ func (s *TransactionsTestSuite) sendTransactionUsingRPCClient( "id": 1, "method": "eth_sendTransaction", "params": [{ - "from": "` + TestConfig.Account1.WalletAddress + `", + "from": "` + utils.TestConfig.Account1.WalletAddress + `", "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", "value": "0x9184e72a" }] @@ -101,26 +106,26 @@ func (s *TransactionsTestSuite) sendTransactionUsingRPCClient( } func (s *TransactionsTestSuite) TestEmptyToFieldPreserved() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) tmpdir, err := ioutil.TempDir("", "transactions-tests-") s.Require().NoError(err) defer os.Remove(tmpdir) - wallet := common.HexToAddress(TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password, + wallet := common.HexToAddress(utils.TestConfig.Account1.WalletAddress) + s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, utils.TestConfig.Account1.Password, []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, e2e.WithDataDir(tmpdir), ) defer s.LogoutAndStop() - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) + utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) args := transactions.SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), } - hash, err := s.Backend.SendTransaction(args, TestConfig.Account1.Password) + hash, err := s.Backend.SendTransaction(args, utils.TestConfig.Account1.Password) s.NoError(err) s.NotNil(hash) } @@ -128,7 +133,7 @@ func (s *TransactionsTestSuite) TestEmptyToFieldPreserved() { // TestSendContractCompat tries to send transaction using the legacy "Data" // field, which is supported for backward compatibility reasons. func (s *TransactionsTestSuite) TestSendContractTxCompat() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { args.Data = (hexutil.Bytes)(byteCode) @@ -140,7 +145,7 @@ func (s *TransactionsTestSuite) TestSendContractTxCompat() { // "Data" and "Input" fields. Also makes sure that the error is returned if // they have different values. func (s *TransactionsTestSuite) TestSendContractTxCollision() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) // Scenario 1: Both fields are filled and have the same value, expect success initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { @@ -167,7 +172,7 @@ func (s *TransactionsTestSuite) TestSendContractTxCollision() { } func (s *TransactionsTestSuite) TestSendContractTx() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) initFunc := func(byteCode []byte, args *transactions.SendTxArgs) { args.Input = (hexutil.Bytes)(byteCode) @@ -180,14 +185,14 @@ func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc s.Require().NoError(err) defer os.Remove(tmpdir) - wallet := common.HexToAddress(TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password, + wallet := common.HexToAddress(utils.TestConfig.Account1.WalletAddress) + s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, utils.TestConfig.Account1.Password, []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, e2e.WithDataDir(tmpdir), ) defer s.LogoutAndStop() - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) + utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) // this call blocks, up until Complete Transaction is called byteCode, err := hexutil.Decode(`0x6060604052341561000c57fe5b5b60a58061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636ffa1caa14603a575bfe5b3415604157fe5b60556004808035906020019091905050606b565b6040518082815260200191505060405180910390f35b60008160020290505b9190505600a165627a7a72305820ccdadd737e4ac7039963b54cee5e5afb25fa859a275252bdcf06f653155228210029`) @@ -195,14 +200,14 @@ func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc gas := uint64(params.DefaultGas) args := transactions.SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), To: nil, // marker, contract creation is expected //Value: (*hexutil.Big)(new(big.Int).Mul(big.NewInt(1), gethcommon.Ether)), Gas: (*hexutil.Uint64)(&gas), } setInputAndDataValue(byteCode, &args) - hash, err := s.Backend.SendTransaction(args, TestConfig.Account1.Password) + hash, err := s.Backend.SendTransaction(args, utils.TestConfig.Account1.Password) if expectedError != nil { s.Equal(expectedError, err, expectedErrorDescription) return @@ -212,40 +217,40 @@ func (s *TransactionsTestSuite) testSendContractTx(setInputAndDataValue initFunc } func (s *TransactionsTestSuite) TestSendEther() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID) tmpdir, err := ioutil.TempDir("", "transactions-tests-") s.Require().NoError(err) defer os.Remove(tmpdir) - wallet := common.HexToAddress(TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password, + wallet := common.HexToAddress(utils.TestConfig.Account1.WalletAddress) + s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, utils.TestConfig.Account1.Password, []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, e2e.WithDataDir(tmpdir), ) defer s.LogoutAndStop() - EnsureNodeSync(s.Backend.StatusNode().EnsureSync) + utils.EnsureNodeSync(s.Backend.StatusNode().EnsureSync) hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), Value: (*hexutil.Big)(big.NewInt(1000000000000)), - }, TestConfig.Account1.Password) + }, utils.TestConfig.Account1.Password) s.NoError(err) s.False(reflect.DeepEqual(hash, gethcommon.Hash{})) } func (s *TransactionsTestSuite) TestSendEtherTxUpstream() { - CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) + utils.CheckTestSkipForNetworks(s.T(), params.MainNetworkID, params.StatusChainNetworkID) tmpdir, err := ioutil.TempDir("", "transactions-tests-") s.Require().NoError(err) defer os.Remove(tmpdir) - addr, err := GetRemoteURL() + addr, err := utils.GetRemoteURL() s.NoError(err) - wallet := common.HexToAddress(TestConfig.Account1.WalletAddress) - s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, TestConfig.Account1.Password, + wallet := common.HexToAddress(utils.TestConfig.Account1.WalletAddress) + s.StartTestBackendWithAccount(multiaccounts.Account{Address: wallet}, utils.TestConfig.Account1.Password, []accounts.Account{{Address: wallet, Wallet: true, Chat: true}}, e2e.WithUpstream(addr), e2e.WithDataDir(tmpdir), @@ -253,11 +258,11 @@ func (s *TransactionsTestSuite) TestSendEtherTxUpstream() { defer s.LogoutAndStop() hash, err := s.Backend.SendTransaction(transactions.SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), GasPrice: (*hexutil.Big)(big.NewInt(28000000000)), Value: (*hexutil.Big)(big.NewInt(1000000000000)), - }, TestConfig.Account1.Password) + }, utils.TestConfig.Account1.Password) s.NoError(err) s.False(reflect.DeepEqual(hash, gethcommon.Hash{})) } diff --git a/t/e2e/whisper/mailservice_test.go b/t/e2e/whisper/mailservice_test.go index 96ea8df50..93b523257 100644 --- a/t/e2e/whisper/mailservice_test.go +++ b/t/e2e/whisper/mailservice_test.go @@ -9,10 +9,12 @@ import ( "github.com/status-im/status-go/node" "github.com/status-im/status-go/params" "github.com/status-im/status-go/t/e2e" + "github.com/status-im/status-go/t/utils" "github.com/stretchr/testify/suite" ) func TestMailServiceSuite(t *testing.T) { + utils.Init() suite.Run(t, new(MailServiceSuite)) } diff --git a/t/e2e/whisper/whisper_mailbox_test.go b/t/e2e/whisper/whisper_mailbox_test.go index 24dd3ec1b..815ea84cc 100644 --- a/t/e2e/whisper/whisper_mailbox_test.go +++ b/t/e2e/whisper/whisper_mailbox_test.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "os" "path/filepath" "sort" "strconv" @@ -12,10 +13,6 @@ import ( "testing" "time" - "github.com/status-im/status-go/services/shhext" - - "os" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" @@ -24,6 +21,7 @@ import ( "github.com/status-im/status-go/mailserver" "github.com/status-im/status-go/params" "github.com/status-im/status-go/rpc" + "github.com/status-im/status-go/services/shhext" "github.com/status-im/status-go/t/helpers" "github.com/status-im/status-go/t/utils" whisper "github.com/status-im/whisper/whisperv6" @@ -38,6 +36,7 @@ type WhisperMailboxSuite struct { } func TestWhisperMailboxTestSuite(t *testing.T) { + utils.Init() suite.Run(t, new(WhisperMailboxSuite)) } @@ -132,7 +131,7 @@ func (s *WhisperMailboxSuite) TestRequestMessageFromMailboxAsync() { s.waitForEnvelopeEvents(envelopeArchivedWatcher, []string{messageHash}, whisper.EventMailServerEnvelopeArchived) // Request messages (including the previous one, expired) from mailbox. - requestID := s.requestHistoricMessagesFromLast12Hours(senderWhisperService, rpcClient, mailboxNode.Server().Self().String(), MailServerKeyID, topic.String(), 0, "") + requestID := s.requestHistoricMessagesFromLast12Hours(senderWhisperService, rpcClient, mailboxNode.Server().Self().URLv4(), MailServerKeyID, topic.String(), 0, "") // wait for mail server response resp := s.waitForMailServerResponse(mailServerResponseWatcher, requestID) @@ -516,7 +515,7 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() { defer stopEmptyMailbox() s.Require().True(emptyMailbox.IsNodeRunning()) - emptyMailboxEnode := emptyMailbox.StatusNode().Server().Self().String() + emptyMailboxEnode := emptyMailbox.StatusNode().Server().Self().URLv4() errCh := helpers.WaitForPeerAsync(emptyMailbox.StatusNode().Server(), mailboxEnode, p2p.PeerEventTypeAdd, 5*time.Second) s.Require().NoError(emptyMailbox.StatusNode().AddPeer(mailboxEnode)) @@ -546,7 +545,7 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() { &syncMessagesResponse, "shhext_syncMessages", shhext.SyncMessagesRequest{ - MailServerPeer: mailbox.StatusNode().Server().Self().String(), + MailServerPeer: mailbox.StatusNode().Server().Self().URLv4(), From: 0, To: uint32(time.Now().Unix()), Limit: 1, @@ -565,7 +564,7 @@ func (s *WhisperMailboxSuite) TestSyncBetweenTwoMailServers() { &syncMessagesResponse, "shhext_syncMessages", shhext.SyncMessagesRequest{ - MailServerPeer: mailbox.StatusNode().Server().Self().String(), + MailServerPeer: mailbox.StatusNode().Server().Self().URLv4(), From: 0, To: uint32(time.Now().Unix()), Limit: 10, diff --git a/t/e2e/whisper/whisper_test.go b/t/e2e/whisper/whisper_test.go index 1e8bf98d5..1eae4e176 100644 --- a/t/e2e/whisper/whisper_test.go +++ b/t/e2e/whisper/whisper_test.go @@ -179,7 +179,7 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() { // select account with wrong password err = s.Backend.SelectAccount(buildLoginParams(accountInfo1.WalletAddress, accountInfo1.ChatAddress, "wrongPassword")) - expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") + expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given password") s.EqualError(expectedErr, err.Error()) // select account with right password diff --git a/t/utils/utils.go b/t/utils/utils.go index 207d8cd33..578927ec9 100644 --- a/t/utils/utils.go +++ b/t/utils/utils.go @@ -58,7 +58,7 @@ var ( syncTimeout = 50 * time.Minute ) -func init() { +func Init() { pwd, err := os.Getwd() if err != nil { panic(err) diff --git a/transactions/transactor_test.go b/transactions/transactor_test.go index e1ea7392f..d493d61fc 100644 --- a/transactions/transactor_test.go +++ b/transactions/transactor_test.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/contracts/ens/contract" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -24,14 +23,16 @@ import ( gethrpc "github.com/ethereum/go-ethereum/rpc" "github.com/golang/mock/gomock" "github.com/status-im/status-go/account" + "github.com/status-im/status-go/contracts/ens/contract" "github.com/status-im/status-go/params" "github.com/status-im/status-go/rpc" - . "github.com/status-im/status-go/t/utils" + "github.com/status-im/status-go/t/utils" "github.com/status-im/status-go/transactions/fake" "github.com/stretchr/testify/suite" ) func TestTransactorSuite(t *testing.T) { + utils.Init() suite.Run(t, new(TransactorSuite)) } @@ -54,7 +55,7 @@ func (s *TransactorSuite) SetupTest() { rpcClient, _ := rpc.NewClient(s.client, params.UpstreamRPCConfig{}) // expected by simulated backend chainID := gethparams.AllEthashProtocolChanges.ChainID.Uint64() - nodeConfig, err := MakeTestNodeConfigWithDataDir("", "/tmp", chainID) + nodeConfig, err := utils.MakeTestNodeConfigWithDataDir("", "/tmp", chainID) s.Require().NoError(err) s.nodeConfig = nodeConfig @@ -120,7 +121,7 @@ func (s *TransactorSuite) rlpEncodeTx(args SendTxArgs, config *params.NodeConfig func (s *TransactorSuite) TestGasValues() { key, _ := crypto.GenerateKey() selectedAccount := &account.SelectedExtKey{ - Address: account.FromAddress(TestConfig.Account1.WalletAddress), + Address: account.FromAddress(utils.TestConfig.Account1.WalletAddress), AccountKey: &keystore.Key{PrivateKey: key}, } testCases := []struct { @@ -154,8 +155,8 @@ func (s *TransactorSuite) TestGasValues() { s.T().Run(testCase.name, func(t *testing.T) { s.SetupTest() args := SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), Gas: testCase.gas, GasPrice: testCase.gasPrice, } @@ -170,14 +171,14 @@ func (s *TransactorSuite) TestGasValues() { func (s *TransactorSuite) TestArgsValidation() { args := SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), Data: hexutil.Bytes([]byte{0x01, 0x02}), Input: hexutil.Bytes([]byte{0x02, 0x01}), } s.False(args.Valid()) selectedAccount := &account.SelectedExtKey{ - Address: account.FromAddress(TestConfig.Account1.WalletAddress), + Address: account.FromAddress(utils.TestConfig.Account1.WalletAddress), } _, err := s.manager.SendTransaction(args, selectedAccount) s.EqualError(err, ErrInvalidSendTxArgs.Error()) @@ -185,8 +186,8 @@ func (s *TransactorSuite) TestArgsValidation() { func (s *TransactorSuite) TestAccountMismatch() { args := SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), } var err error @@ -197,7 +198,7 @@ func (s *TransactorSuite) TestAccountMismatch() { // mismatched accounts selectedAccount := &account.SelectedExtKey{ - Address: account.FromAddress(TestConfig.Account2.WalletAddress), + Address: account.FromAddress(utils.TestConfig.Account2.WalletAddress), } _, err = s.manager.SendTransaction(args, selectedAccount) s.EqualError(err, ErrInvalidTxSender.Error()) @@ -214,15 +215,15 @@ func (s *TransactorSuite) TestLocalNonce() { txCount := 3 key, _ := crypto.GenerateKey() selectedAccount := &account.SelectedExtKey{ - Address: account.FromAddress(TestConfig.Account1.WalletAddress), + Address: account.FromAddress(utils.TestConfig.Account1.WalletAddress), AccountKey: &keystore.Key{PrivateKey: key}, } nonce := hexutil.Uint64(0) for i := 0; i < txCount; i++ { args := SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), } s.setupTransactionPoolAPI(args, nonce, hexutil.Uint64(i), selectedAccount, nil) @@ -234,8 +235,8 @@ func (s *TransactorSuite) TestLocalNonce() { nonce = hexutil.Uint64(5) args := SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), } s.setupTransactionPoolAPI(args, nonce, nonce, selectedAccount, nil) @@ -249,8 +250,8 @@ func (s *TransactorSuite) TestLocalNonce() { testErr := errors.New("test") s.txServiceMock.EXPECT().GetTransactionCount(gomock.Any(), selectedAccount.Address, gethrpc.PendingBlockNumber).Return(nil, testErr) args = SendTxArgs{ - From: account.FromAddress(TestConfig.Account1.WalletAddress), - To: account.ToAddress(TestConfig.Account2.WalletAddress), + From: account.FromAddress(utils.TestConfig.Account1.WalletAddress), + To: account.ToAddress(utils.TestConfig.Account2.WalletAddress), } _, err = s.manager.SendTransaction(args, selectedAccount) diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE new file mode 100644 index 000000000..ae80b6720 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Stack Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/StackExchange/wmi/README.md b/vendor/github.com/StackExchange/wmi/README.md new file mode 100644 index 000000000..426d1a46b --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/README.md @@ -0,0 +1,6 @@ +wmi +=== + +Package wmi provides a WQL interface to Windows WMI. + +Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. diff --git a/vendor/github.com/StackExchange/wmi/swbemservices.go b/vendor/github.com/StackExchange/wmi/swbemservices.go new file mode 100644 index 000000000..9765a53f7 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/swbemservices.go @@ -0,0 +1,260 @@ +// +build windows + +package wmi + +import ( + "fmt" + "reflect" + "runtime" + "sync" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx +type SWbemServices struct { + //TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance + cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method + sWbemLocatorIUnknown *ole.IUnknown + sWbemLocatorIDispatch *ole.IDispatch + queries chan *queryRequest + closeError chan error + lQueryorClose sync.Mutex +} + +type queryRequest struct { + query string + dst interface{} + args []interface{} + finished chan error +} + +// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI +func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) { + //fmt.Println("InitializeSWbemServices: Starting") + //TODO: implement connectServerArgs as optional argument for init with connectServer call + s := new(SWbemServices) + s.cWMIClient = c + s.queries = make(chan *queryRequest) + initError := make(chan error) + go s.process(initError) + + err, ok := <-initError + if ok { + return nil, err //Send error to caller + } + //fmt.Println("InitializeSWbemServices: Finished") + return s, nil +} + +// Close will clear and release all of the SWbemServices resources +func (s *SWbemServices) Close() error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + //fmt.Println("Close: sending close request") + var result error + ce := make(chan error) + s.closeError = ce //Race condition if multiple callers to close. May need to lock here + close(s.queries) //Tell background to shut things down + s.lQueryorClose.Unlock() + err, ok := <-ce + if ok { + result = err + } + //fmt.Println("Close: finished") + return result +} + +func (s *SWbemServices) process(initError chan error) { + //fmt.Println("process: starting background thread initialization") + //All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine + runtime.LockOSThread() + defer runtime.LockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err) + return + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err) + return + } else if unknown == nil { + initError <- ErrNilCreateObject + return + } + defer unknown.Release() + s.sWbemLocatorIUnknown = unknown + + dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err) + return + } + defer dispatch.Release() + s.sWbemLocatorIDispatch = dispatch + + // we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs + //fmt.Println("process: initialized. closing initError") + close(initError) + //fmt.Println("process: waiting for queries") + for q := range s.queries { + //fmt.Printf("process: new query: len(query)=%d\n", len(q.query)) + errQuery := s.queryBackground(q) + //fmt.Println("process: s.queryBackground finished") + if errQuery != nil { + q.finished <- errQuery + } + close(q.finished) + } + //fmt.Println("process: queries channel closed") + s.queries = nil //set channel to nil so we know it is closed + //TODO: I think the Release/Clear calls can panic if things are in a bad state. + //TODO: May need to recover from panics and send error to method caller instead. + close(s.closeError) +} + +// Query runs the WQL query using a SWbemServices instance and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + + //fmt.Println("Query: Sending query request") + qr := queryRequest{ + query: query, + dst: dst, + args: connectServerArgs, + finished: make(chan error), + } + s.queries <- &qr + s.lQueryorClose.Unlock() + err, ok := <-qr.finished + if ok { + //fmt.Println("Query: Finished with error") + return err //Send error to caller + } + //fmt.Println("Query: Finished") + return nil +} + +func (s *SWbemServices) queryBackground(q *queryRequest) error { + if s == nil || s.sWbemLocatorIDispatch == nil { + return fmt.Errorf("SWbemServices is not Initialized") + } + wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart + //fmt.Println("queryBackground: Starting") + + dv := reflect.ValueOf(q.dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + //fmt.Println("queryBackground: Finished") + return errFieldMismatch +} diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go new file mode 100644 index 000000000..a951b1258 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/wmi.go @@ -0,0 +1,486 @@ +// +build windows + +/* +Package wmi provides a WQL interface for WMI on Windows. + +Example code to print names of running processes: + + type Win32_Process struct { + Name string + } + + func main() { + var dst []Win32_Process + q := wmi.CreateQuery(&dst, "") + err := wmi.Query(q, &dst) + if err != nil { + log.Fatal(err) + } + for i, v := range dst { + println(i, v.Name) + } + } + +*/ +package wmi + +import ( + "bytes" + "errors" + "fmt" + "log" + "os" + "reflect" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +var l = log.New(os.Stdout, "", log.LstdFlags) + +var ( + ErrInvalidEntityType = errors.New("wmi: invalid entity type") + // ErrNilCreateObject is the error returned if CreateObject returns nil even + // if the error was nil. + ErrNilCreateObject = errors.New("wmi: create object returned nil") + lock sync.Mutex +) + +// S_FALSE is returned by CoInitializeEx if it was already called on this thread. +const S_FALSE = 0x00000001 + +// QueryNamespace invokes Query with the given namespace on the local machine. +func QueryNamespace(query string, dst interface{}, namespace string) error { + return Query(query, dst, nil, namespace) +} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +// +// Query is a wrapper around DefaultClient.Query. +func Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + if DefaultClient.SWbemServicesClient == nil { + return DefaultClient.Query(query, dst, connectServerArgs...) + } + return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...) +} + +// A Client is an WMI query client. +// +// Its zero value (DefaultClient) is a usable client. +type Client struct { + // NonePtrZero specifies if nil values for fields which aren't pointers + // should be returned as the field types zero value. + // + // Setting this to true allows stucts without pointer fields to be used + // without the risk failure should a nil value returned from WMI. + NonePtrZero bool + + // PtrNil specifies if nil values for pointer fields should be returned + // as nil. + // + // Setting this to true will set pointer fields to nil where WMI + // returned nil, otherwise the types zero value will be returned. + PtrNil bool + + // AllowMissingFields specifies that struct fields not present in the + // query result should not result in an error. + // + // Setting this to true allows custom queries to be used with full + // struct definitions instead of having to define multiple structs. + AllowMissingFields bool + + // SWbemServiceClient is an optional SWbemServices object that can be + // initialized and then reused across multiple queries. If it is null + // then the method will initialize a new temporary client each time. + SWbemServicesClient *SWbemServices +} + +// DefaultClient is the default Client and is used by Query, QueryNamespace +var DefaultClient = &Client{} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (c *Client) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + dv := reflect.ValueOf(dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + lock.Lock() + defer lock.Unlock() + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + return err + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + return err + } else if unknown == nil { + return ErrNilCreateObject + } + defer unknown.Release() + + wmi, err := unknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + return err + } + defer wmi.Release() + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", connectServerArgs...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = c.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + return errFieldMismatch +} + +// ErrFieldMismatch is returned when a field is to be loaded into a different +// type than the one it was stored from, or when a field is missing or +// unexported in the destination struct. +// StructType is the type of the struct pointed to by the destination argument. +type ErrFieldMismatch struct { + StructType reflect.Type + FieldName string + Reason string +} + +func (e *ErrFieldMismatch) Error() string { + return fmt.Sprintf("wmi: cannot load field %q into a %q: %s", + e.FieldName, e.StructType, e.Reason) +} + +var timeType = reflect.TypeOf(time.Time{}) + +// loadEntity loads a SWbemObject into a struct pointer. +func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) { + v := reflect.ValueOf(dst).Elem() + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + of := f + isPtr := f.Kind() == reflect.Ptr + if isPtr { + ptr := reflect.New(f.Type().Elem()) + f.Set(ptr) + f = f.Elem() + } + n := v.Type().Field(i).Name + if !f.CanSet() { + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "CanSet() is false", + } + } + prop, err := oleutil.GetProperty(src, n) + if err != nil { + if !c.AllowMissingFields { + errFieldMismatch = &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "no such struct field", + } + } + continue + } + defer prop.Clear() + + switch val := prop.Value().(type) { + case int8, int16, int32, int64, int: + v := reflect.ValueOf(val).Int() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(v) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(uint64(v)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case uint8, uint16, uint32, uint64: + v := reflect.ValueOf(val).Uint() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(int64(v)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(v) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case string: + switch f.Kind() { + case reflect.String: + f.SetString(val) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + iv, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return err + } + f.SetInt(iv) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uv, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return err + } + f.SetUint(uv) + case reflect.Struct: + switch f.Type() { + case timeType: + if len(val) == 25 { + mins, err := strconv.Atoi(val[22:]) + if err != nil { + return err + } + val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60) + } + t, err := time.Parse("20060102150405.000000-0700", val) + if err != nil { + return err + } + f.Set(reflect.ValueOf(t)) + } + } + case bool: + switch f.Kind() { + case reflect.Bool: + f.SetBool(val) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a bool", + } + } + case float32: + switch f.Kind() { + case reflect.Float32: + f.SetFloat(float64(val)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a Float32", + } + } + default: + if f.Kind() == reflect.Slice { + switch f.Type().Elem().Kind() { + case reflect.String: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetString(v.(string)) + } + f.Set(fArr) + } + case reflect.Uint8: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetUint(reflect.ValueOf(v).Uint()) + } + f.Set(fArr) + } + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported slice type (%T)", val), + } + } + } else { + typeof := reflect.TypeOf(val) + if typeof == nil && (isPtr || c.NonePtrZero) { + if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) { + of.Set(reflect.Zero(of.Type())) + } + break + } + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported type (%T)", val), + } + } + } + } + return errFieldMismatch +} + +type multiArgType int + +const ( + multiArgTypeInvalid multiArgType = iota + multiArgTypeStruct + multiArgTypeStructPtr +) + +// checkMultiArg checks that v has type []S, []*S for some struct type S. +// +// It returns what category the slice's elements are, and the reflect.Type +// that represents S. +func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) { + if v.Kind() != reflect.Slice { + return multiArgTypeInvalid, nil + } + elemType = v.Type().Elem() + switch elemType.Kind() { + case reflect.Struct: + return multiArgTypeStruct, elemType + case reflect.Ptr: + elemType = elemType.Elem() + if elemType.Kind() == reflect.Struct { + return multiArgTypeStructPtr, elemType + } + } + return multiArgTypeInvalid, nil +} + +func oleInt64(item *ole.IDispatch, prop string) (int64, error) { + v, err := oleutil.GetProperty(item, prop) + if err != nil { + return 0, err + } + defer v.Clear() + + i := int64(v.Val) + return i, nil +} + +// CreateQuery returns a WQL query string that queries all columns of src. where +// is an optional string that is appended to the query, to be used with WHERE +// clauses. In such a case, the "WHERE" string should appear at the beginning. +func CreateQuery(src interface{}, where string) string { + var b bytes.Buffer + b.WriteString("SELECT ") + s := reflect.Indirect(reflect.ValueOf(src)) + t := s.Type() + if s.Kind() == reflect.Slice { + t = t.Elem() + } + if t.Kind() != reflect.Struct { + return "" + } + var fields []string + for i := 0; i < t.NumField(); i++ { + fields = append(fields, t.Field(i).Name) + } + b.WriteString(strings.Join(fields, ", ")) + b.WriteString(" FROM ") + b.WriteString(t.Name()) + b.WriteString(" " + where) + return b.String() +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go new file mode 100644 index 000000000..d4a9c1b83 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/genprecomps.go @@ -0,0 +1,63 @@ +// Copyright 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// This file is ignored during the regular build due to the following build tag. +// It is called by go generate and used to automatically generate pre-computed +// tables used to accelerate operations. +// +build ignore + +package main + +import ( + "bytes" + "compress/zlib" + "encoding/base64" + "fmt" + "log" + "os" + + "github.com/btcsuite/btcd/btcec" +) + +func main() { + fi, err := os.Create("secp256k1.go") + if err != nil { + log.Fatal(err) + } + defer fi.Close() + + // Compress the serialized byte points. + serialized := btcec.S256().SerializedBytePoints() + var compressed bytes.Buffer + w := zlib.NewWriter(&compressed) + if _, err := w.Write(serialized); err != nil { + fmt.Println(err) + os.Exit(1) + } + w.Close() + + // Encode the compressed byte points with base64. + encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len())) + base64.StdEncoding.Encode(encoded, compressed.Bytes()) + + fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers") + fmt.Fprintln(fi, "// Use of this source code is governed by an ISC") + fmt.Fprintln(fi, "// license that can be found in the LICENSE file.") + fmt.Fprintln(fi) + fmt.Fprintln(fi, "package btcec") + fmt.Fprintln(fi) + fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)") + fmt.Fprintln(fi, "// DO NOT EDIT") + fmt.Fprintln(fi) + fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded)) + + a1, b1, a2, b2 := btcec.S256().EndomorphismVectors() + fmt.Println("The following values are the computed linearly " + + "independent vectors needed to make use of the secp256k1 " + + "endomorphism:") + fmt.Printf("a1: %x\n", a1) + fmt.Printf("b1: %x\n", b1) + fmt.Printf("a2: %x\n", a2) + fmt.Printf("b2: %x\n", b2) +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/signature.go b/vendor/github.com/btcsuite/btcd/btcec/signature.go index bddb22831..f1c437749 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/signature.go +++ b/vendor/github.com/btcsuite/btcd/btcec/signature.go @@ -85,10 +85,10 @@ func (sig *Signature) IsEqual(otherSig *Signature) bool { sig.S.Cmp(otherSig.S) == 0 } -// minSigLen is the minimum length of a DER encoded signature and is -// when both R and S are 1 byte each. +// MinSigLen is the minimum length of a DER encoded signature and is when both R +// and S are 1 byte each. // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + -const minSigLen = 8 +const MinSigLen = 8 func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the @@ -103,7 +103,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) signature := &Signature{} - if len(sigStr) < minSigLen { + if len(sigStr) < MinSigLen { return nil, errors.New("malformed signature: too short") } // 0x30 @@ -118,7 +118,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // siglen should be less than the entire message and greater than // the minimal message size. - if int(siglen+2) > len(sigStr) || int(siglen+2) < minSigLen { + if int(siglen+2) > len(sigStr) || int(siglen+2) < MinSigLen { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. diff --git a/vendor/github.com/btcsuite/btcd/wire/message.go b/vendor/github.com/btcsuite/btcd/wire/message.go index 4f03cf564..e93764770 100644 --- a/vendor/github.com/btcsuite/btcd/wire/message.go +++ b/vendor/github.com/btcsuite/btcd/wire/message.go @@ -321,9 +321,13 @@ func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, return totalBytes, err } - // Write payload. - n, err = w.Write(payload) - totalBytes += n + // Only write the payload if there is one, e.g., verack messages don't + // have one. + if len(payload) > 0 { + n, err = w.Write(payload) + totalBytes += n + } + return totalBytes, err } diff --git a/vendor/github.com/btcsuite/btcutil/base58/genalphabet.go b/vendor/github.com/btcsuite/btcutil/base58/genalphabet.go new file mode 100644 index 000000000..010cbee39 --- /dev/null +++ b/vendor/github.com/btcsuite/btcutil/base58/genalphabet.go @@ -0,0 +1,79 @@ +// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +//+build ignore + +package main + +import ( + "bytes" + "io" + "log" + "os" + "strconv" +) + +var ( + start = []byte(`// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// AUTOGENERATED by genalphabet.go; do not edit. + +package base58 + +const ( + // alphabet is the modified base58 alphabet used by Bitcoin. + alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + alphabetIdx0 = '1' +) + +var b58 = [256]byte{`) + + end = []byte(`}`) + + alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") + tab = []byte("\t") + invalid = []byte("255") + comma = []byte(",") + space = []byte(" ") + nl = []byte("\n") +) + +func write(w io.Writer, b []byte) { + _, err := w.Write(b) + if err != nil { + log.Fatal(err) + } +} + +func main() { + fi, err := os.Create("alphabet.go") + if err != nil { + log.Fatal(err) + } + defer fi.Close() + + write(fi, start) + write(fi, nl) + for i := byte(0); i < 32; i++ { + write(fi, tab) + for j := byte(0); j < 8; j++ { + idx := bytes.IndexByte(alphabet, i*8+j) + if idx == -1 { + write(fi, invalid) + } else { + write(fi, strconv.AppendInt(nil, int64(idx), 10)) + } + write(fi, comma) + if j != 7 { + write(fi, space) + } + } + write(fi, nl) + } + write(fi, end) + write(fi, nl) +} diff --git a/vendor/github.com/elastic/gosigar/.appveyor.yml b/vendor/github.com/elastic/gosigar/.appveyor.yml new file mode 100644 index 000000000..ff467086d --- /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 000000000..6f145056f --- /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 000000000..30f58bfcf --- /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 000000000..45262e7b8 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md @@ -0,0 +1,113 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +### Added + +### Fixed + +- Added missing runtime import for FreeBSD. #104 + +### Changed + +### Deprecated + +## [0.9.0] + +### Added +- Added support for huge TLB pages on Linux #97 +- Added support for big endian platform #100 + +### Fixed +- Add missing method for OpenBSD #99 + +## [0.8.0] + +### Added +- Added partial `getrusage` support for Windows to retrieve system CPU time and user CPU time. #95 +- Added full `getrusage` support for Unix. #95 + +## [0.7.0] + +### Added +- Added method stubs for process handling for operating system that are not supported + by gosigar. All methods return `ErrNotImplemented` on such systems. #88 + +### Fixed +- Fix freebsd build by using the common version of Get(pid). #91 + +### Changed +- Fixed issues in cgroup package by adding missing error checks and closing + file handles. #92 + +## [0.6.0] + +### Added +- Added method stubs to enable compilation for operating systems that are not + supported by gosigar. All methods return `ErrNotImplemented` on these unsupported + operating systems. #83 +- FreeBSD returns `ErrNotImplemented` for `ProcTime.Get`. #83 + +### Changed +- OpenBSD returns `ErrNotImplemented` for `ProcTime.Get` instead of `nil`. #83 +- Fixed incorrect `Mem.Used` calculation under linux. #82 +- Fixed `ProcState` on Linux and FreeBSD when process names contain parentheses. #81 + +### Removed +- Remove NetBSD build from sigar_unix.go as it is not supported by gosigar. #83 + +## [0.5.0] + +### Changed +- Fixed Trim environment variables when comparing values in the test suite. #79 +- Make `kern_procargs` more robust under darwin when we cannot retrieve + all the information about a process. #78 + +## [0.4.0] + +### Changed +- Fixed Windows issue that caused a hang during `init()` if WMI wasn't ready. #74 + +## [0.3.0] + +### Added +- Read `MemAvailable` value for kernel 3.14+ #71 + +## [0.2.0] + +### Added +- Added `ErrCgroupsMissing` to indicate that /proc/cgroups is missing which is + an indicator that cgroups were disabled at compile time. #64 + +### Changed +- Changed `cgroup.SupportedSubsystems()` to honor the "enabled" column in the + /proc/cgroups file. #64 + +## [0.1.0] + +### Added +- Added `CpuList` implementation for Windows that returns CPU timing information + on a per CPU basis. #55 +- Added `Uptime` implementation for Windows. #55 +- Added `Swap` implementation for Windows based on page file metrics. #55 +- Added support to `github.com/gosigar/sys/windows` for querying and enabling + privileges in a process token. +- Added utility code for interfacing with linux NETLINK_INET_DIAG. #60 +- Added `ProcEnv` for getting a process's environment variables. #61 + +### Changed +- Changed several `OpenProcess` calls on Windows to request the lowest possible + access privileges. #50 +- Removed cgo usage from Windows code. +- Added OS version checks to `ProcArgs.Get` on Windows because the + `Win32_Process` WMI query is not available prior to Windows vista. On XP and + Windows 2003, this method returns `ErrNotImplemented`. #55 + +### Fixed +- Fixed value of `Mem.ActualFree` and `Mem.ActualUsed` on Windows. #49 +- Fixed `ProcTime.StartTime` on Windows to report value in milliseconds since + Unix epoch. #51 +- Fixed `ProcStatus.PPID` value is wrong on Windows. #55 +- Fixed `ProcStatus.Username` error on Windows XP #56 diff --git a/vendor/github.com/elastic/gosigar/LICENSE b/vendor/github.com/elastic/gosigar/LICENSE new file mode 100644 index 000000000..11069edd7 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/elastic/gosigar/NOTICE b/vendor/github.com/elastic/gosigar/NOTICE new file mode 100644 index 000000000..fda553b5c --- /dev/null +++ b/vendor/github.com/elastic/gosigar/NOTICE @@ -0,0 +1,9 @@ +Copyright (c) [2009-2011] VMware, Inc. All Rights Reserved. + +This product is licensed to you under the Apache License, Version 2.0 (the "License"). +You may not use this product except in compliance with the License. + +This product includes a number of subcomponents with +separate copyright notices and license terms. Your use of these +subcomponents is subject to the terms and conditions of the +subcomponent's license, as noted in the LICENSE file. \ No newline at end of file diff --git a/vendor/github.com/elastic/gosigar/README.md b/vendor/github.com/elastic/gosigar/README.md new file mode 100644 index 000000000..ecdfc1c3c --- /dev/null +++ b/vendor/github.com/elastic/gosigar/README.md @@ -0,0 +1,58 @@ +# 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 | +| HugeTLBPages | X | | | | | +| LoadAverage | X | X | | X | X | +| Mem | X | X | X | X | X | +| ProcArgs | X | X | X | | X | +| ProcEnv | X | X | | | X | +| ProcExe | X | X | | | X | +| ProcFDUsage | X | | | | X | +| ProcList | X | X | X | | X | +| ProcMem | X | X | X | | X | +| ProcState | X | X | X | | X | +| ProcTime | X | X | X | | X | +| Swap | X | X | | X | X | +| Uptime | X | X | | X | X | + +## OS Specific Notes + +### FreeBSD + +Mount both `linprocfs` and `procfs` for compatability. Consider adding these +mounts to your `/etc/fstab` file so they are mounted automatically at boot. + +``` +sudo mount -t procfs proc /proc +sudo mkdir -p /compat/linux/proc +sudo mount -t linprocfs /dev/null /compat/linux/proc +``` + +## License + +Apache 2.0 diff --git a/vendor/github.com/elastic/gosigar/Vagrantfile b/vendor/github.com/elastic/gosigar/Vagrantfile new file mode 100644 index 000000000..6fd990c14 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/Vagrantfile @@ -0,0 +1,25 @@ +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "hashicorp/precise64" + config.vm.provision "shell", inline: "mkdir -p /home/vagrant/go" + config.vm.synced_folder ".", "/home/vagrant/go/src/github.com/cloudfoundry/gosigar" + config.vm.provision "shell", inline: "chown -R vagrant:vagrant /home/vagrant/go" + install_go = <<-BASH + set -e + +if [ ! -d "/usr/local/go" ]; then + cd /tmp && wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz + cd /usr/local + tar xvzf /tmp/go1.3.3.linux-amd64.tar.gz + echo 'export GOPATH=/home/vagrant/go; export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin' >> /home/vagrant/.bashrc +fi +export GOPATH=/home/vagrant/go +export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin +/usr/local/go/bin/go get -u github.com/onsi/ginkgo/ginkgo +/usr/local/go/bin/go get -u github.com/onsi/gomega; +BASH + config.vm.provision "shell", inline: 'apt-get install -y git-core' + config.vm.provision "shell", inline: install_go +end diff --git a/vendor/github.com/elastic/gosigar/codecov.yml b/vendor/github.com/elastic/gosigar/codecov.yml new file mode 100644 index 000000000..76ade0fdb --- /dev/null +++ b/vendor/github.com/elastic/gosigar/codecov.yml @@ -0,0 +1,21 @@ +# Enable coverage report message for diff on commit +coverage: + status: + project: off + patch: + default: + # basic + target: auto + threshold: null + base: auto + # advanced + branches: null + if_no_uploads: error + if_not_found: success + if_ci_failed: error + only_pulls: false + flags: null + paths: null + +# Disable comments on Pull Requests +comment: false diff --git a/vendor/github.com/elastic/gosigar/concrete_sigar.go b/vendor/github.com/elastic/gosigar/concrete_sigar.go new file mode 100644 index 000000000..e3ee80a98 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/concrete_sigar.go @@ -0,0 +1,89 @@ +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) GetHugeTLBPages() (HugeTLBPages, error) { + p := HugeTLBPages{} + err := p.Get() + return p, err +} + +func (c *ConcreteSigar) GetFileSystemUsage(path string) (FileSystemUsage, error) { + f := FileSystemUsage{} + err := f.Get(path) + return f, err +} + +func (c *ConcreteSigar) GetFDUsage() (FDUsage, error) { + fd := FDUsage{} + err := fd.Get() + return fd, err +} + +// GetRusage return the resource usage of the process +// Possible params: 0 = RUSAGE_SELF, 1 = RUSAGE_CHILDREN, 2 = RUSAGE_THREAD +func (c *ConcreteSigar) GetRusage(who int) (Rusage, error) { + r := Rusage{} + err := r.Get(who) + return r, err +} diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin.go b/vendor/github.com/elastic/gosigar/sigar_darwin.go new file mode 100644 index 000000000..a90b998c2 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_darwin.go @@ -0,0 +1,498 @@ +// 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 *HugeTLBPages) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *Cpu) Get() error { + var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT + var cpuload C.host_cpu_load_info_data_t + + status := C.host_statistics(C.host_t(C.mach_host_self()), + C.HOST_CPU_LOAD_INFO, + C.host_info_t(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return fmt.Errorf("host_statistics error=%d", status) + } + + self.User = uint64(cpuload.cpu_ticks[C.CPU_STATE_USER]) + self.Sys = uint64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) + self.Idle = uint64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) + self.Nice = uint64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) + + return nil +} + +func (self *CpuList) Get() error { + var count C.mach_msg_type_number_t + var cpuload *C.processor_cpu_load_info_data_t + var ncpu C.natural_t + + status := C.host_processor_info(C.host_t(C.mach_host_self()), + C.PROCESSOR_CPU_LOAD_INFO, + &ncpu, + (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return fmt.Errorf("host_processor_info error=%d", status) + } + + // jump through some cgo casting hoops and ensure we properly free + // the memory that cpuload points to + target := C.vm_map_t(C.mach_task_self_) + address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) + defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) + + // the body of struct processor_cpu_load_info + // aka processor_cpu_load_info_data_t + var cpu_ticks [C.CPU_STATE_MAX]uint32 + + // copy the cpuload array to a []byte buffer + // where we can binary.Read the data + size := int(ncpu) * binary.Size(cpu_ticks) + buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size)) + + bbuf := bytes.NewBuffer(buf) + + self.List = make([]Cpu, 0, ncpu) + + for i := 0; i < int(ncpu); i++ { + cpu := Cpu{} + + err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) + if err != nil { + return err + } + + cpu.User = uint64(cpu_ticks[C.CPU_STATE_USER]) + cpu.Sys = uint64(cpu_ticks[C.CPU_STATE_SYSTEM]) + cpu.Idle = uint64(cpu_ticks[C.CPU_STATE_IDLE]) + cpu.Nice = uint64(cpu_ticks[C.CPU_STATE_NICE]) + + self.List = append(self.List, cpu) + } + + return nil +} + +func (self *FDUsage) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *FileSystemList) Get() error { + num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT) + if err != nil { + return err + } + + buf := make([]syscall.Statfs_t, num) + + _, err = syscall.Getfsstat(buf, C.MNT_NOWAIT) + if err != nil { + return err + } + + fslist := make([]FileSystem, 0, num) + + for i := 0; i < num; i++ { + fs := FileSystem{} + + fs.DirName = bytePtrToString(&buf[i].Mntonname[0]) + fs.DevName = bytePtrToString(&buf[i].Mntfromname[0]) + fs.SysTypeName = bytePtrToString(&buf[i].Fstypename[0]) + + fslist = append(fslist, fs) + } + + self.List = fslist + + return err +} + +func (self *ProcList) Get() error { + n := C.proc_listpids(C.PROC_ALL_PIDS, 0, nil, 0) + if n <= 0 { + return syscall.EINVAL + } + buf := make([]byte, n) + n = C.proc_listpids(C.PROC_ALL_PIDS, 0, unsafe.Pointer(&buf[0]), n) + if n <= 0 { + return syscall.ENOMEM + } + + var pid int32 + num := int(n) / binary.Size(pid) + list := make([]int, 0, num) + bbuf := bytes.NewBuffer(buf) + + for i := 0; i < num; i++ { + if err := binary.Read(bbuf, binary.LittleEndian, &pid); err != nil { + return err + } + if pid == 0 { + continue + } + + list = append(list, int(pid)) + } + + self.List = list + + return nil +} + +func (self *ProcState) Get(pid int) error { + info := C.struct_proc_taskallinfo{} + + if err := task_info(pid, &info); err != nil { + return err + } + + self.Name = C.GoString(&info.pbsd.pbi_comm[0]) + + switch info.pbsd.pbi_status { + case C.SIDL: + self.State = RunStateIdle + case C.SRUN: + self.State = RunStateRun + case C.SSLEEP: + self.State = RunStateSleep + case C.SSTOP: + self.State = RunStateStop + case C.SZOMB: + self.State = RunStateZombie + default: + self.State = RunStateUnknown + } + + self.Ppid = int(info.pbsd.pbi_ppid) + + self.Pgid = int(info.pbsd.pbi_pgid) + + self.Tty = int(info.pbsd.e_tdev) + + self.Priority = int(info.ptinfo.pti_priority) + + self.Nice = int(info.pbsd.pbi_nice) + + // Get process username. Fallback to UID if username is not available. + uid := strconv.Itoa(int(info.pbsd.pbi_uid)) + user, err := user.LookupId(uid) + if err == nil && user.Username != "" { + self.Username = user.Username + } else { + self.Username = uid + } + + return nil +} + +func (self *ProcMem) Get(pid int) error { + info := C.struct_proc_taskallinfo{} + + if err := task_info(pid, &info); err != nil { + return err + } + + self.Size = uint64(info.ptinfo.pti_virtual_size) + self.Resident = uint64(info.ptinfo.pti_resident_size) + self.PageFaults = uint64(info.ptinfo.pti_faults) + + return nil +} + +func (self *ProcTime) Get(pid int) error { + info := C.struct_proc_taskallinfo{} + + if err := task_info(pid, &info); err != nil { + return err + } + + self.User = + uint64(info.ptinfo.pti_total_user) / uint64(time.Millisecond) + + self.Sys = + uint64(info.ptinfo.pti_total_system) / uint64(time.Millisecond) + + self.Total = self.User + self.Sys + + self.StartTime = (uint64(info.pbsd.pbi_start_tvsec) * 1000) + + (uint64(info.pbsd.pbi_start_tvusec) / 1000) + + return nil +} + +func (self *ProcArgs) Get(pid int) error { + var args []string + + argv := func(arg string) { + args = append(args, arg) + } + + err := kern_procargs(pid, nil, argv, nil) + + self.List = args + + return err +} + +func (self *ProcEnv) Get(pid int) error { + if self.Vars == nil { + self.Vars = map[string]string{} + } + + env := func(k, v string) { + self.Vars[k] = v + } + + return kern_procargs(pid, nil, nil, env) +} + +func (self *ProcExe) Get(pid int) error { + exe := func(arg string) { + self.Name = arg + } + + return kern_procargs(pid, exe, nil, nil) +} + +func (self *ProcFDUsage) Get(pid int) error { + return ErrNotImplemented{runtime.GOOS} +} + +// wrapper around sysctl KERN_PROCARGS2 +// callbacks params are optional, +// up to the caller as to which pieces of data they want +func kern_procargs(pid int, + exe func(string), + argv func(string), + env func(string, string)) error { + + mib := []C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)} + argmax := uintptr(C.ARG_MAX) + buf := make([]byte, argmax) + err := sysctl(mib, &buf[0], &argmax, nil, 0) + if err != nil { + return nil + } + + bbuf := bytes.NewBuffer(buf) + bbuf.Truncate(int(argmax)) + + var argc int32 + binary.Read(bbuf, binary.LittleEndian, &argc) + + path, err := bbuf.ReadBytes(0) + if err != nil { + return fmt.Errorf("Error reading the argv[0]: %v", err) + } + if exe != nil { + exe(string(chop(path))) + } + + // skip trailing \0's + for { + c, err := bbuf.ReadByte() + if err != nil { + return fmt.Errorf("Error skipping nils: %v", err) + } + if c != 0 { + bbuf.UnreadByte() + break // start of argv[0] + } + } + + for i := 0; i < int(argc); i++ { + arg, err := bbuf.ReadBytes(0) + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("Error reading args: %v", err) + } + if argv != nil { + argv(string(chop(arg))) + } + } + + if env == nil { + return nil + } + + delim := []byte{61} // "=" + + for { + line, err := bbuf.ReadBytes(0) + if err == io.EOF || line[0] == 0 { + break + } + if err != nil { + return fmt.Errorf("Error reading args: %v", err) + } + pair := bytes.SplitN(chop(line), delim, 2) + + if len(pair) != 2 { + return fmt.Errorf("Error reading process information for PID: %d", pid) + } + + env(string(pair[0]), string(pair[1])) + } + + return nil +} + +// XXX copied from zsyscall_darwin_amd64.go +func sysctl(mib []C.int, old *byte, oldlen *uintptr, + new *byte, newlen uintptr) (err error) { + var p0 unsafe.Pointer + p0 = unsafe.Pointer(&mib[0]) + _, _, e1 := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = e1 + } + return +} + +func vm_info(vmstat *C.vm_statistics_data_t) error { + var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT + + status := C.host_statistics( + C.host_t(C.mach_host_self()), + C.HOST_VM_INFO, + C.host_info_t(unsafe.Pointer(vmstat)), + &count) + + if status != C.KERN_SUCCESS { + return fmt.Errorf("host_statistics=%d", status) + } + + return nil +} + +// generic Sysctl buffer unmarshalling +func sysctlbyname(name string, data interface{}) (err error) { + val, err := syscall.Sysctl(name) + if err != nil { + return err + } + + buf := []byte(val) + + switch v := data.(type) { + case *uint64: + *v = *(*uint64)(unsafe.Pointer(&buf[0])) + return + } + + bbuf := bytes.NewBuffer([]byte(val)) + return binary.Read(bbuf, binary.LittleEndian, data) +} + +func task_info(pid int, info *C.struct_proc_taskallinfo) error { + size := C.int(unsafe.Sizeof(*info)) + ptr := unsafe.Pointer(info) + + n := C.proc_pidinfo(C.int(pid), C.PROC_PIDTASKALLINFO, 0, ptr, size) + if n != size { + return fmt.Errorf("Could not read process info for pid %d", pid) + } + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_format.go b/vendor/github.com/elastic/gosigar/sigar_format.go new file mode 100644 index 000000000..ac56c9873 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_format.go @@ -0,0 +1,126 @@ +// Copyright (c) 2012 VMware, Inc. + +package gosigar + +import ( + "bufio" + "bytes" + "fmt" + "strconv" + "time" +) + +// Go version of apr_strfsize +func FormatSize(size uint64) string { + ord := []string{"K", "M", "G", "T", "P", "E"} + o := 0 + buf := new(bytes.Buffer) + w := bufio.NewWriter(buf) + + if size < 973 { + fmt.Fprintf(w, "%3d ", size) + w.Flush() + return buf.String() + } + + for { + remain := size & 1023 + size >>= 10 + + if size >= 973 { + o++ + continue + } + + if size < 9 || (size == 9 && remain < 973) { + remain = ((remain * 5) + 256) / 512 + if remain >= 10 { + size++ + remain = 0 + } + + fmt.Fprintf(w, "%d.%d%s", size, remain, ord[o]) + break + } + + if remain >= 512 { + size++ + } + + fmt.Fprintf(w, "%3d%s", size, ord[o]) + break + } + + w.Flush() + return buf.String() +} + +func FormatPercent(percent float64) string { + return strconv.FormatFloat(percent, 'f', -1, 64) + "%" +} + +func (self *FileSystemUsage) UsePercent() float64 { + b_used := (self.Total - self.Free) / 1024 + b_avail := self.Avail / 1024 + utotal := b_used + b_avail + used := b_used + + if utotal != 0 { + u100 := used * 100 + pct := u100 / utotal + if u100%utotal != 0 { + pct += 1 + } + return (float64(pct) / float64(100)) * 100.0 + } + + return 0.0 +} + +func (self *Uptime) Format() string { + buf := new(bytes.Buffer) + w := bufio.NewWriter(buf) + uptime := uint64(self.Length) + + days := uptime / (60 * 60 * 24) + + if days != 0 { + s := "" + if days > 1 { + s = "s" + } + fmt.Fprintf(w, "%d day%s, ", days, s) + } + + minutes := uptime / 60 + hours := minutes / 60 + hours %= 24 + minutes %= 60 + + fmt.Fprintf(w, "%2d:%02d", hours, minutes) + + w.Flush() + return buf.String() +} + +func (self *ProcTime) FormatStartTime() string { + if self.StartTime == 0 { + return "00:00" + } + start := time.Unix(int64(self.StartTime)/1000, 0) + format := "Jan02" + if time.Since(start).Seconds() < (60 * 60 * 24) { + format = "15:04" + } + return start.Format(format) +} + +func (self *ProcTime) FormatTotal() string { + t := self.Total / 1000 + ss := t % 60 + t /= 60 + mm := t % 60 + t /= 60 + hh := t % 24 + return fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss) +} diff --git a/vendor/github.com/elastic/gosigar/sigar_freebsd.go b/vendor/github.com/elastic/gosigar/sigar_freebsd.go new file mode 100644 index 000000000..9b2af639b --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_freebsd.go @@ -0,0 +1,113 @@ +// Copied and modified from sigar_linux.go. + +package gosigar + +import ( + "io/ioutil" + "runtime" + "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 (self *HugeTLBPages) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func parseCpuStat(self *Cpu, line string) error { + fields := strings.Fields(line) + + self.User, _ = strtoull(fields[1]) + self.Nice, _ = strtoull(fields[2]) + self.Sys, _ = strtoull(fields[3]) + self.Idle, _ = strtoull(fields[4]) + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_interface.go b/vendor/github.com/elastic/gosigar/sigar_interface.go new file mode 100644 index 000000000..df79ae08d --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_interface.go @@ -0,0 +1,207 @@ +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) + GetHugeTLBPages(HugeTLBPages, 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 HugeTLBPages struct { + Total uint64 + Free uint64 + Reserved uint64 + Surplus uint64 + DefaultSize uint64 + TotalAllocatedSize uint64 +} + +type CpuList struct { + List []Cpu +} + +type FDUsage struct { + Open uint64 + Unused uint64 + Max uint64 +} + +type FileSystem struct { + DirName string + DevName string + TypeName string + SysTypeName string + Options string + Flags uint32 +} + +type FileSystemList struct { + List []FileSystem +} + +type FileSystemUsage struct { + Total uint64 + Used uint64 + Free uint64 + Avail uint64 + Files uint64 + FreeFiles uint64 +} + +type ProcList struct { + List []int +} + +type RunState byte + +const ( + RunStateSleep = 'S' + RunStateRun = 'R' + RunStateStop = 'T' + RunStateZombie = 'Z' + RunStateIdle = 'D' + RunStateUnknown = '?' +) + +type ProcState struct { + Name string + Username string + State RunState + Ppid int + Pgid int + Tty int + Priority int + Nice int + Processor int +} + +type ProcMem struct { + Size uint64 + Resident uint64 + Share uint64 + MinorFaults uint64 + MajorFaults uint64 + PageFaults uint64 +} + +type ProcTime struct { + StartTime uint64 + User uint64 + Sys uint64 + Total uint64 +} + +type ProcArgs struct { + List []string +} + +type ProcEnv struct { + Vars map[string]string +} + +type ProcExe struct { + Name string + Cwd string + Root string +} + +type ProcFDUsage struct { + Open uint64 + SoftLimit uint64 + HardLimit uint64 +} + +type Rusage struct { + Utime time.Duration + Stime time.Duration + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} diff --git a/vendor/github.com/elastic/gosigar/sigar_linux.go b/vendor/github.com/elastic/gosigar/sigar_linux.go new file mode 100644 index 000000000..09f2e30b2 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_linux.go @@ -0,0 +1,108 @@ +// 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 *HugeTLBPages) Get() error { + table, err := parseMeminfo() + if err != nil { + return err + } + + self.Total, _ = table["HugePages_Total"] + self.Free, _ = table["HugePages_Free"] + self.Reserved, _ = table["HugePages_Rsvd"] + self.Surplus, _ = table["HugePages_Surp"] + self.DefaultSize, _ = table["Hugepagesize"] + + if totalSize, found := table["Hugetlb"]; found { + self.TotalAllocatedSize = totalSize + } else { + // If Hugetlb is not present, or huge pages of different sizes + // are used, this figure can be unaccurate. + // TODO (jsoriano): Extract information from /sys/kernel/mm/hugepages too + self.TotalAllocatedSize = (self.Total - self.Free + self.Reserved) * self.DefaultSize + } + + return nil +} + +func (self *ProcFDUsage) Get(pid int) error { + err := readFile(procFileName(pid, "limits"), func(line string) bool { + if strings.HasPrefix(line, "Max open files") { + fields := strings.Fields(line) + if len(fields) == 6 { + self.SoftLimit, _ = strconv.ParseUint(fields[3], 10, 64) + self.HardLimit, _ = strconv.ParseUint(fields[4], 10, 64) + } + return false + } + return true + }) + if err != nil { + return err + } + fds, err := ioutil.ReadDir(procFileName(pid, "fd")) + if err != nil { + return err + } + self.Open = uint64(len(fds)) + return nil +} + +func parseCpuStat(self *Cpu, line string) error { + fields := strings.Fields(line) + + self.User, _ = strtoull(fields[1]) + self.Nice, _ = strtoull(fields[2]) + self.Sys, _ = strtoull(fields[3]) + self.Idle, _ = strtoull(fields[4]) + self.Wait, _ = strtoull(fields[5]) + self.Irq, _ = strtoull(fields[6]) + self.SoftIrq, _ = strtoull(fields[7]) + self.Stolen, _ = strtoull(fields[8]) + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_linux_common.go b/vendor/github.com/elastic/gosigar/sigar_linux_common.go new file mode 100644 index 000000000..7ca649762 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_linux_common.go @@ -0,0 +1,482 @@ +// 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 + } + + valueUnit := strings.Fields(fields[1]) + value, err := strtoull(valueUnit[0]) + if err != nil { + return true // skip on errors + } + + if len(valueUnit) > 1 && valueUnit[1] == "kB" { + value *= 1024 + } + table[fields[0]] = value + + 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) (content []byte, err error) { + path := procFileName(pid, name) + + // Panics have been reported when reading proc files, let's recover and + // report the path if this happens + // See https://github.com/elastic/beats/issues/6692 + defer func() { + if r := recover(); r != nil { + content = nil + err = fmt.Errorf("recovered panic when reading proc file '%s': %v", path, r) + } + }() + contents, err := ioutil.ReadFile(path) + + if err != nil { + if perr, ok := err.(*os.PathError); ok { + if perr.Err == syscall.ENOENT { + return nil, syscall.ESRCH + } + } + } + + return contents, err +} + +// getProcStatus reads /proc/[pid]/status which contains process status +// information in human readable form. +func getProcStatus(pid int) (map[string]string, error) { + status := make(map[string]string, 42) + path := filepath.Join(Procd, strconv.Itoa(pid), "status") + err := readFile(path, func(line string) bool { + fields := strings.SplitN(line, ":", 2) + if len(fields) == 2 { + status[fields[0]] = strings.TrimSpace(fields[1]) + } + + return true + }) + return status, err +} + +// getUIDs reads the "Uid" value from status and splits it into four values -- +// real, effective, saved set, and file system UIDs. +func getUIDs(status map[string]string) ([]string, error) { + uidLine, ok := status["Uid"] + if !ok { + return nil, fmt.Errorf("Uid not found in proc status") + } + + uidStrs := strings.Fields(uidLine) + if len(uidStrs) != 4 { + return nil, fmt.Errorf("Uid line ('%s') did not contain four values", uidLine) + } + + return uidStrs, nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_openbsd.go b/vendor/github.com/elastic/gosigar/sigar_openbsd.go new file mode 100644 index 000000000..e4371b8b6 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_openbsd.go @@ -0,0 +1,426 @@ +// 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 *HugeTLBPages) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +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 (self *Rusage) Get(pid int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func fillCpu(cpu *Cpu, load [C.CPUSTATES]C.long) { + cpu.User = uint64(load[0]) + cpu.Nice = uint64(load[1]) + cpu.Sys = uint64(load[2]) + cpu.Irq = uint64(load[3]) + cpu.Idle = uint64(load[4]) +} + +func sysctlCptime(ncpu int, curcpu int, load *[C.CPUSTATES]C.long) error { + var mib []int32 + + // Use the correct mib based on the number of CPUs and fill out the + // current CPU number in case of SMP. (0 indexed cf. self.List) + if ncpu == 0 { + mib = []int32{C.CTL_KERN, C.KERN_CPTIME} + } else { + mib = []int32{C.CTL_KERN, C.KERN_CPTIME2, int32(curcpu)} + } + + len := len(mib) + + n := uintptr(0) + // First we determine how much memory we'll need to pass later on (via `n`) + _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), 0, uintptr(unsafe.Pointer(&n)), 0, 0) + if errno != 0 || n == 0 { + return nil + } + + _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), uintptr(unsafe.Pointer(load)), uintptr(unsafe.Pointer(&n)), 0, 0) + if errno != 0 || n == 0 { + return nil + } + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sigar_stub.go b/vendor/github.com/elastic/gosigar/sigar_stub.go new file mode 100644 index 000000000..de9565aec --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_stub.go @@ -0,0 +1,75 @@ +// +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 (s *HugeTLBPages) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (f *FDUsage) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcTime) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *FileSystemUsage) Get(path string) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *CpuList) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcState) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcExe) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcMem) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcFDUsage) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcEnv) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcList) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (p *ProcArgs) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *Rusage) Get(int) error { + return ErrNotImplemented{runtime.GOOS} +} diff --git a/vendor/github.com/elastic/gosigar/sigar_unix.go b/vendor/github.com/elastic/gosigar/sigar_unix.go new file mode 100644 index 000000000..3f3a9f7ff --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_unix.go @@ -0,0 +1,69 @@ +// Copyright (c) 2012 VMware, Inc. + +// +build darwin freebsd linux + +package gosigar + +import ( + "syscall" + "time" + + "golang.org/x/sys/unix" +) + +func (self *FileSystemUsage) Get(path string) error { + stat := syscall.Statfs_t{} + err := syscall.Statfs(path, &stat) + if err != nil { + return err + } + + self.Total = uint64(stat.Blocks) * uint64(stat.Bsize) + self.Free = uint64(stat.Bfree) * uint64(stat.Bsize) + self.Avail = uint64(stat.Bavail) * uint64(stat.Bsize) + self.Used = self.Total - self.Free + self.Files = stat.Files + self.FreeFiles = uint64(stat.Ffree) + + return nil +} + +func (r *Rusage) Get(who int) error { + ru, err := getResourceUsage(who) + if err != nil { + return err + } + + uTime := convertRtimeToDur(ru.Utime) + sTime := convertRtimeToDur(ru.Stime) + + r.Utime = uTime + r.Stime = sTime + r.Maxrss = int64(ru.Maxrss) + r.Ixrss = int64(ru.Ixrss) + r.Idrss = int64(ru.Idrss) + r.Isrss = int64(ru.Isrss) + r.Minflt = int64(ru.Minflt) + r.Majflt = int64(ru.Majflt) + r.Nswap = int64(ru.Nswap) + r.Inblock = int64(ru.Inblock) + r.Oublock = int64(ru.Oublock) + r.Msgsnd = int64(ru.Msgsnd) + r.Msgrcv = int64(ru.Msgrcv) + r.Nsignals = int64(ru.Nsignals) + r.Nvcsw = int64(ru.Nvcsw) + r.Nivcsw = int64(ru.Nivcsw) + + return nil +} + +func getResourceUsage(who int) (unix.Rusage, error) { + r := unix.Rusage{} + err := unix.Getrusage(who, &r) + + return r, err +} + +func convertRtimeToDur(t unix.Timeval) time.Duration { + return time.Duration(t.Nano()) +} diff --git a/vendor/github.com/elastic/gosigar/sigar_util.go b/vendor/github.com/elastic/gosigar/sigar_util.go new file mode 100644 index 000000000..bf93b02b2 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_util.go @@ -0,0 +1,22 @@ +// Copyright (c) 2012 VMware, Inc. + +package gosigar + +import ( + "unsafe" +) + +func bytePtrToString(ptr *int8) string { + bytes := (*[10000]byte)(unsafe.Pointer(ptr)) + + n := 0 + for bytes[n] != 0 { + n++ + } + + return string(bytes[0:n]) +} + +func chop(buf []byte) []byte { + return buf[0 : len(buf)-1] +} diff --git a/vendor/github.com/elastic/gosigar/sigar_windows.go b/vendor/github.com/elastic/gosigar/sigar_windows.go new file mode 100644 index 000000000..c2b54d8d7 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_windows.go @@ -0,0 +1,441 @@ +// 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 *HugeTLBPages) Get() error { + return ErrNotImplemented{runtime.GOOS} +} + +func (self *Cpu) Get() error { + idle, kernel, user, err := windows.GetSystemTimes() + if err != nil { + return errors.Wrap(err, "GetSystemTimes failed") + } + + // CPU times are reported in milliseconds by gosigar. + self.Idle = uint64(idle / time.Millisecond) + self.Sys = uint64(kernel / time.Millisecond) + self.User = uint64(user / time.Millisecond) + return nil +} + +func (self *CpuList) Get() error { + cpus, err := windows.NtQuerySystemProcessorPerformanceInformation() + if err != nil { + return errors.Wrap(err, "NtQuerySystemProcessorPerformanceInformation failed") + } + + self.List = make([]Cpu, 0, len(cpus)) + for _, cpu := range cpus { + self.List = append(self.List, Cpu{ + Idle: uint64(cpu.IdleTime / time.Millisecond), + Sys: uint64(cpu.KernelTime / time.Millisecond), + User: uint64(cpu.UserTime / time.Millisecond), + }) + } + return nil +} + +func (self *FileSystemList) Get() error { + drives, err := windows.GetLogicalDriveStrings() + if err != nil { + return errors.Wrap(err, "GetLogicalDriveStrings failed") + } + + for _, drive := range drives { + dt, err := windows.GetDriveType(drive) + if err != nil { + return errors.Wrapf(err, "GetDriveType failed") + } + + self.List = append(self.List, FileSystem{ + DirName: drive, + DevName: drive, + TypeName: dt.String(), + }) + } + return nil +} + +// Get retrieves a list of all process identifiers (PIDs) in the system. +func (self *ProcList) Get() error { + pids, err := windows.EnumProcesses() + if err != nil { + return errors.Wrap(err, "EnumProcesses failed") + } + + // Convert uint32 PIDs to int. + self.List = make([]int, 0, len(pids)) + for _, pid := range pids { + self.List = append(self.List, int(pid)) + } + return nil +} + +func (self *ProcState) Get(pid int) error { + var errs []error + + var err error + self.Name, err = getProcName(pid) + if err != nil { + errs = append(errs, errors.Wrap(err, "getProcName failed")) + } + + self.State, err = getProcStatus(pid) + if err != nil { + errs = append(errs, errors.Wrap(err, "getProcStatus failed")) + } + + self.Ppid, err = getParentPid(pid) + if err != nil { + errs = append(errs, errors.Wrap(err, "getParentPid failed")) + } + + self.Username, err = getProcCredName(pid) + if err != nil { + errs = append(errs, errors.Wrap(err, "getProcCredName failed")) + } + + if len(errs) > 0 { + errStrs := make([]string, 0, len(errs)) + for _, e := range errs { + errStrs = append(errStrs, e.Error()) + } + return errors.New(strings.Join(errStrs, "; ")) + } + return nil +} + +// getProcName returns the process name associated with the PID. +func getProcName(pid int) (string, error) { + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid)) + if err != nil { + return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + filename, err := windows.GetProcessImageFileName(handle) + if err != nil { + return "", errors.Wrapf(err, "GetProcessImageFileName failed for pid=%v", pid) + } + + return filepath.Base(filename), nil +} + +// getProcStatus returns the status of a process. +func getProcStatus(pid int) (RunState, error) { + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid)) + if err != nil { + return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + var exitCode uint32 + err = syscall.GetExitCodeProcess(handle, &exitCode) + if err != nil { + return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v") + } + + if exitCode == 259 { //still active + return RunStateRun, nil + } + return RunStateSleep, nil +} + +// getParentPid returns the parent process ID of a process. +func getParentPid(pid int) (int, error) { + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid)) + if err != nil { + return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + procInfo, err := windows.NtQueryProcessBasicInformation(handle) + if err != nil { + return 0, errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid) + } + + return int(procInfo.InheritedFromUniqueProcessID), nil +} + +func getProcCredName(pid int) (string, error) { + handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid)) + if err != nil { + return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + // Find process token via win32. + var token syscall.Token + err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token) + if err != nil { + return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid) + } + + // Find the token user. + tokenUser, err := token.GetTokenUser() + if err != nil { + return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid) + } + + // Close token to prevent handle leaks. + err = token.Close() + if err != nil { + return "", errors.Wrapf(err, "failed while closing process token handle for pid=%v", pid) + } + + // Look up domain account by SID. + account, domain, _, err := tokenUser.User.Sid.LookupAccount("") + if err != nil { + sid, sidErr := tokenUser.User.Sid.String() + if sidErr != nil { + return "", errors.Wrapf(err, "failed while looking up account name for pid=%v", pid) + } + return "", errors.Wrapf(err, "failed while looking up account name for SID=%v of pid=%v", sid, pid) + } + + return fmt.Sprintf(`%s\%s`, domain, account), nil +} + +func (self *ProcMem) Get(pid int) error { + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid)) + if err != nil { + return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + counters, err := windows.GetProcessMemoryInfo(handle) + if err != nil { + return errors.Wrapf(err, "GetProcessMemoryInfo failed for pid=%v", pid) + } + + self.Resident = uint64(counters.WorkingSetSize) + self.Size = uint64(counters.PrivateUsage) + return nil +} + +func (self *ProcTime) Get(pid int) error { + cpu, err := getProcTimes(pid) + if err != nil { + return err + } + + // Windows epoch times are expressed as time elapsed since midnight on + // January 1, 1601 at Greenwich, England. This converts the Filetime to + // unix epoch in milliseconds. + self.StartTime = uint64(cpu.CreationTime.Nanoseconds() / 1e6) + + // Convert to millis. + self.User = uint64(windows.FiletimeToDuration(&cpu.UserTime).Nanoseconds() / 1e6) + self.Sys = uint64(windows.FiletimeToDuration(&cpu.KernelTime).Nanoseconds() / 1e6) + self.Total = self.User + self.Sys + + return nil +} + +func getProcTimes(pid int) (*syscall.Rusage, error) { + handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid)) + if err != nil { + return nil, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid) + } + defer syscall.CloseHandle(handle) + + var cpu syscall.Rusage + if err := syscall.GetProcessTimes(handle, &cpu.CreationTime, &cpu.ExitTime, &cpu.KernelTime, &cpu.UserTime); err != nil { + return nil, errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid) + } + + return &cpu, nil +} + +func (self *ProcArgs) Get(pid int) error { + // The minimum supported client for Win32_Process is Windows Vista. + if !version.IsWindowsVistaOrGreater() { + return ErrNotImplemented{runtime.GOOS} + } + + process, err := getWin32Process(int32(pid)) + if err != nil { + return errors.Wrapf(err, "ProcArgs failed for pid=%v", pid) + } + + self.List = []string{process.CommandLine} + return nil +} + +func (self *FileSystemUsage) Get(path string) error { + freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, err := windows.GetDiskFreeSpaceEx(path) + if err != nil { + return errors.Wrap(err, "GetDiskFreeSpaceEx failed") + } + + self.Total = totalNumberOfBytes + self.Free = totalNumberOfFreeBytes + self.Used = self.Total - self.Free + self.Avail = freeBytesAvailable + return nil +} + +// getWin32Process gets information about the process with the given process ID. +// It uses a WMI query to get the information from the local system. +func getWin32Process(pid int32) (Win32_Process, error) { + var dst []Win32_Process + query := fmt.Sprintf("WHERE ProcessId = %d", pid) + q := wmi.CreateQuery(&dst, query) + err := wmi.Query(q, &dst) + if err != nil { + return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: %v", query, err) + } + if len(dst) < 1 { + return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: Process not found", query) + } + return dst[0], nil +} + +func getWin32OperatingSystem() (Win32_OperatingSystem, error) { + var dst []Win32_OperatingSystem + q := wmi.CreateQuery(&dst, "") + err := wmi.Query(q, &dst) + if err != nil { + return Win32_OperatingSystem{}, errors.Wrap(err, "wmi query for Win32_OperatingSystem failed") + } + if len(dst) != 1 { + return Win32_OperatingSystem{}, errors.New("wmi query for Win32_OperatingSystem failed") + } + return dst[0], nil +} + +func (self *Rusage) Get(who int) error { + if who != 0 { + return ErrNotImplemented{runtime.GOOS} + } + + pid := os.Getpid() + cpu, err := getProcTimes(pid) + if err != nil { + return err + } + + self.Utime = windows.FiletimeToDuration(&cpu.UserTime) + self.Stime = windows.FiletimeToDuration(&cpu.KernelTime) + + return nil +} diff --git a/vendor/github.com/elastic/gosigar/sys/windows/doc.go b/vendor/github.com/elastic/gosigar/sys/windows/doc.go new file mode 100644 index 000000000..dda57aa83 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/doc.go @@ -0,0 +1,2 @@ +// Package windows contains various Windows system call. +package windows diff --git a/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go b/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go new file mode 100644 index 000000000..85de365e1 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go @@ -0,0 +1,132 @@ +// +build windows + +package windows + +import ( + "bytes" + "encoding/binary" + "io" + "runtime" + "syscall" + "time" + "unsafe" + + "github.com/pkg/errors" +) + +// On both 32-bit and 64-bit systems NtQuerySystemInformation expects the +// size of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION to be 48. +const sizeofSystemProcessorPerformanceInformation = 48 + +// ProcessBasicInformation is an equivalent representation of +// PROCESS_BASIC_INFORMATION in the Windows API. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx +type ProcessBasicInformation struct { + ExitStatus uint + PebBaseAddress uintptr + AffinityMask uint + BasePriority uint + UniqueProcessID uint + InheritedFromUniqueProcessID uint +} + +// NtQueryProcessBasicInformation queries basic information about the process +// associated with the given handle (provided by OpenProcess). It uses the +// NtQueryInformationProcess function to collect the data. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx +func NtQueryProcessBasicInformation(handle syscall.Handle) (ProcessBasicInformation, error) { + var processBasicInfo ProcessBasicInformation + processBasicInfoPtr := (*byte)(unsafe.Pointer(&processBasicInfo)) + size := uint32(unsafe.Sizeof(processBasicInfo)) + ntStatus, _ := _NtQueryInformationProcess(handle, 0, processBasicInfoPtr, size, nil) + if ntStatus != 0 { + return ProcessBasicInformation{}, errors.Errorf("NtQueryInformationProcess failed, NTSTATUS=0x%X", ntStatus) + } + + return processBasicInfo, nil +} + +// SystemProcessorPerformanceInformation contains CPU performance information +// for a single CPU. +type SystemProcessorPerformanceInformation struct { + IdleTime time.Duration // Amount of time spent idle. + KernelTime time.Duration // Kernel time does NOT include time spent in idle. + UserTime time.Duration // Amount of time spent executing in user mode. +} + +// _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION is an equivalent representation of +// SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION in the Windows API. This struct is +// used internally with NtQuerySystemInformation call and is not exported. The +// exported equivalent is SystemProcessorPerformanceInformation. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx +type _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION struct { + IdleTime int64 + KernelTime int64 + UserTime int64 + Reserved1 [2]int64 + Reserved2 uint32 +} + +// NtQuerySystemProcessorPerformanceInformation queries CPU performance +// information for each CPU. It uses the NtQuerySystemInformation function to +// collect the SystemProcessorPerformanceInformation. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx +func NtQuerySystemProcessorPerformanceInformation() ([]SystemProcessorPerformanceInformation, error) { + // NTSTATUS code for success. + // https://msdn.microsoft.com/en-us/library/cc704588.aspx + const STATUS_SUCCESS = 0 + + // From the _SYSTEM_INFORMATION_CLASS enum. + // http://processhacker.sourceforge.net/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0 + const systemProcessorPerformanceInformation = 8 + + // Create a buffer large enough to hold an entry for each processor. + b := make([]byte, runtime.NumCPU()*sizeofSystemProcessorPerformanceInformation) + + // Query the performance information. Note that this function uses 0 to + // indicate success. Most other Windows functions use non-zero for success. + var returnLength uint32 + ntStatus, _ := _NtQuerySystemInformation(systemProcessorPerformanceInformation, &b[0], uint32(len(b)), &returnLength) + if ntStatus != STATUS_SUCCESS { + return nil, errors.Errorf("NtQuerySystemInformation failed, NTSTATUS=0x%X, bufLength=%v, returnLength=%v", ntStatus, len(b), returnLength) + } + + return readSystemProcessorPerformanceInformationBuffer(b) +} + +// readSystemProcessorPerformanceInformationBuffer reads from a buffer +// containing SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION data. The buffer should +// contain one entry for each CPU. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx +func readSystemProcessorPerformanceInformationBuffer(b []byte) ([]SystemProcessorPerformanceInformation, error) { + n := len(b) / sizeofSystemProcessorPerformanceInformation + r := bytes.NewReader(b) + + rtn := make([]SystemProcessorPerformanceInformation, 0, n) + for i := 0; i < n; i++ { + _, err := r.Seek(int64(i*sizeofSystemProcessorPerformanceInformation), io.SeekStart) + if err != nil { + return nil, errors.Wrapf(err, "failed to seek to cpuN=%v in buffer", i) + } + + times := make([]uint64, 3) + for j := range times { + err := binary.Read(r, binary.LittleEndian, ×[j]) + if err != nil { + return nil, errors.Wrapf(err, "failed reading cpu times for cpuN=%v", i) + } + } + + idleTime := time.Duration(times[0] * 100) + kernelTime := time.Duration(times[1] * 100) + userTime := time.Duration(times[2] * 100) + + rtn = append(rtn, SystemProcessorPerformanceInformation{ + IdleTime: idleTime, + KernelTime: kernelTime - idleTime, // Subtract out idle time from kernel time. + UserTime: userTime, + }) + } + + return rtn, nil +} diff --git a/vendor/github.com/elastic/gosigar/sys/windows/privileges.go b/vendor/github.com/elastic/gosigar/sys/windows/privileges.go new file mode 100644 index 000000000..28c78fd22 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/privileges.go @@ -0,0 +1,272 @@ +// +build windows + +package windows + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "runtime" + "strings" + "sync" + "syscall" + + "github.com/pkg/errors" + "golang.org/x/sys/windows" +) + +// Cache of privilege names to LUIDs. +var ( + privNames = make(map[string]int64) + privNameMutex sync.Mutex +) + +const ( + // SeDebugPrivilege is the name of the privilege used to debug programs. + SeDebugPrivilege = "SeDebugPrivilege" +) + +// Errors returned by AdjustTokenPrivileges. +const ( + ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 +) + +// Attribute bits for privileges. +const ( + _SE_PRIVILEGE_ENABLED_BY_DEFAULT uint32 = 0x00000001 + _SE_PRIVILEGE_ENABLED uint32 = 0x00000002 + _SE_PRIVILEGE_REMOVED uint32 = 0x00000004 + _SE_PRIVILEGE_USED_FOR_ACCESS uint32 = 0x80000000 +) + +// Privilege contains information about a single privilege associated with a +// Token. +type Privilege struct { + LUID int64 `json:"-"` // Locally unique identifier (guaranteed only until the system is restarted). + Name string `json:"-"` + EnabledByDefault bool `json:"enabled_by_default,omitempty"` + Enabled bool `json:"enabled"` + Removed bool `json:"removed,omitempty"` + Used bool `json:"used,omitempty"` +} + +func (p Privilege) String() string { + var buf bytes.Buffer + buf.WriteString(p.Name) + buf.WriteString("=(") + + opts := make([]string, 0, 4) + if p.EnabledByDefault { + opts = append(opts, "Default") + } + if p.Enabled { + opts = append(opts, "Enabled") + } + if !p.EnabledByDefault && !p.Enabled { + opts = append(opts, "Disabled") + } + if p.Removed { + opts = append(opts, "Removed") + } + if p.Used { + opts = append(opts, "Used") + } + + buf.WriteString(strings.Join(opts, ", ")) + buf.WriteString(")") + + // Example: SeDebugPrivilege=(Default, Enabled) + return buf.String() +} + +// User represent the information about a Windows account. +type User struct { + SID string + Account string + Domain string + Type uint32 +} + +func (u User) String() string { + return fmt.Sprintf(`User:%v\%v, SID:%v, Type:%v`, u.Domain, u.Account, u.SID, u.Type) +} + +// DebugInfo contains general debug info about the current process. +type DebugInfo struct { + OSVersion Version // OS version info. + Arch string // Architecture of the machine. + NumCPU int // Number of CPUs. + User User // User that this process is running as. + ProcessPrivs map[string]Privilege // Privileges held by the process. +} + +func (d DebugInfo) String() string { + bytes, _ := json.Marshal(d) + return string(bytes) +} + +// LookupPrivilegeName looks up a privilege name given a LUID value. +func LookupPrivilegeName(systemName string, luid int64) (string, error) { + buf := make([]uint16, 256) + bufSize := uint32(len(buf)) + err := _LookupPrivilegeName(systemName, &luid, &buf[0], &bufSize) + if err != nil { + return "", errors.Wrapf(err, "LookupPrivilegeName failed for luid=%v", luid) + } + + return syscall.UTF16ToString(buf), nil +} + +// mapPrivileges maps privilege names to LUID values. +func mapPrivileges(names []string) ([]int64, error) { + var privileges []int64 + privNameMutex.Lock() + defer privNameMutex.Unlock() + for _, name := range names { + p, ok := privNames[name] + if !ok { + err := _LookupPrivilegeValue("", name, &p) + if err != nil { + return nil, errors.Wrapf(err, "LookupPrivilegeValue failed on '%v'", name) + } + privNames[name] = p + } + privileges = append(privileges, p) + } + return privileges, nil +} + +// EnableTokenPrivileges enables the specified privileges in the given +// Token. The token must have TOKEN_ADJUST_PRIVILEGES access. If the token +// does not already contain the privilege it cannot be enabled. +func EnableTokenPrivileges(token syscall.Token, privileges ...string) error { + privValues, err := mapPrivileges(privileges) + if err != nil { + return err + } + + var b bytes.Buffer + binary.Write(&b, binary.LittleEndian, uint32(len(privValues))) + for _, p := range privValues { + binary.Write(&b, binary.LittleEndian, p) + binary.Write(&b, binary.LittleEndian, uint32(_SE_PRIVILEGE_ENABLED)) + } + + success, err := _AdjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(b.Len()), nil, nil) + if !success { + return err + } + if err == ERROR_NOT_ALL_ASSIGNED { + return errors.Wrap(err, "error not all privileges were assigned") + } + + return nil +} + +// GetTokenPrivileges returns a list of privileges associated with a token. +// The provided token must have at a minimum TOKEN_QUERY access. This is a +// wrapper around the GetTokenInformation function. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx +func GetTokenPrivileges(token syscall.Token) (map[string]Privilege, error) { + // Determine the required buffer size. + var size uint32 + syscall.GetTokenInformation(token, syscall.TokenPrivileges, nil, 0, &size) + + // This buffer will receive a TOKEN_PRIVILEGE structure. + b := bytes.NewBuffer(make([]byte, size)) + err := syscall.GetTokenInformation(token, syscall.TokenPrivileges, &b.Bytes()[0], uint32(b.Len()), &size) + if err != nil { + return nil, errors.Wrap(err, "GetTokenInformation failed") + } + + var privilegeCount uint32 + err = binary.Read(b, binary.LittleEndian, &privilegeCount) + if err != nil { + return nil, errors.Wrap(err, "failed to read PrivilegeCount") + } + + rtn := make(map[string]Privilege, privilegeCount) + for i := 0; i < int(privilegeCount); i++ { + var luid int64 + err = binary.Read(b, binary.LittleEndian, &luid) + if err != nil { + return nil, errors.Wrap(err, "failed to read LUID value") + } + + var attributes uint32 + err = binary.Read(b, binary.LittleEndian, &attributes) + if err != nil { + return nil, errors.Wrap(err, "failed to read attributes") + } + + name, err := LookupPrivilegeName("", luid) + if err != nil { + return nil, errors.Wrapf(err, "LookupPrivilegeName failed for LUID=%v", luid) + } + + rtn[name] = Privilege{ + LUID: luid, + Name: name, + EnabledByDefault: (attributes & _SE_PRIVILEGE_ENABLED_BY_DEFAULT) > 0, + Enabled: (attributes & _SE_PRIVILEGE_ENABLED) > 0, + Removed: (attributes & _SE_PRIVILEGE_REMOVED) > 0, + Used: (attributes & _SE_PRIVILEGE_USED_FOR_ACCESS) > 0, + } + } + + return rtn, nil +} + +// GetTokenUser returns the User associated with the given Token. +func GetTokenUser(token syscall.Token) (User, error) { + tokenUser, err := token.GetTokenUser() + if err != nil { + return User{}, errors.Wrap(err, "GetTokenUser failed") + } + + var user User + user.SID, err = tokenUser.User.Sid.String() + if err != nil { + return user, errors.Wrap(err, "ConvertSidToStringSid failed") + } + + user.Account, user.Domain, user.Type, err = tokenUser.User.Sid.LookupAccount("") + if err != nil { + return user, errors.Wrap(err, "LookupAccountSid failed") + } + + return user, nil +} + +// GetDebugInfo returns general debug info about the current process. +func GetDebugInfo() (*DebugInfo, error) { + h, err := windows.GetCurrentProcess() + if err != nil { + return nil, err + } + + var token syscall.Token + err = syscall.OpenProcessToken(syscall.Handle(h), syscall.TOKEN_QUERY, &token) + if err != nil { + return nil, err + } + + privs, err := GetTokenPrivileges(token) + if err != nil { + return nil, err + } + + user, err := GetTokenUser(token) + if err != nil { + return nil, err + } + + return &DebugInfo{ + User: user, + ProcessPrivs: privs, + OSVersion: GetWindowsVersion(), + Arch: runtime.GOARCH, + NumCPU: runtime.NumCPU(), + }, nil +} diff --git a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go new file mode 100644 index 000000000..88df0febf --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go @@ -0,0 +1,385 @@ +package windows + +import ( + "fmt" + "syscall" + "time" + "unsafe" + + "github.com/pkg/errors" +) + +var ( + sizeofUint32 = 4 + sizeofProcessEntry32 = uint32(unsafe.Sizeof(ProcessEntry32{})) + sizeofProcessMemoryCountersEx = uint32(unsafe.Sizeof(ProcessMemoryCountersEx{})) + sizeofMemoryStatusEx = uint32(unsafe.Sizeof(MemoryStatusEx{})) +) + +// Process-specific access rights. Others are declared in the syscall package. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx +const ( + PROCESS_QUERY_LIMITED_INFORMATION uint32 = 0x1000 + PROCESS_VM_READ uint32 = 0x0010 +) + +// MAX_PATH is the maximum length for a path in Windows. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx +const MAX_PATH = 260 + +// DriveType represents a type of drive (removable, fixed, CD-ROM, RAM disk, or +// network drive). +type DriveType uint32 + +// Drive types as returned by GetDriveType. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939(v=vs.85).aspx +const ( + DRIVE_UNKNOWN DriveType = iota + DRIVE_NO_ROOT_DIR + DRIVE_REMOVABLE + DRIVE_FIXED + DRIVE_REMOTE + DRIVE_CDROM + DRIVE_RAMDISK +) + +func (dt DriveType) String() string { + names := map[DriveType]string{ + DRIVE_UNKNOWN: "unknown", + DRIVE_NO_ROOT_DIR: "invalid", + DRIVE_REMOVABLE: "removable", + DRIVE_FIXED: "fixed", + DRIVE_REMOTE: "remote", + DRIVE_CDROM: "cdrom", + DRIVE_RAMDISK: "ramdisk", + } + + name, found := names[dt] + if !found { + return "unknown DriveType value" + } + return name +} + +// Flags that can be used with CreateToolhelp32Snapshot. +const ( + TH32CS_INHERIT uint32 = 0x80000000 // Indicates that the snapshot handle is to be inheritable. + TH32CS_SNAPHEAPLIST uint32 = 0x00000001 // Includes all heaps of the process specified in th32ProcessID in the snapshot. + TH32CS_SNAPMODULE uint32 = 0x00000008 // Includes all modules of the process specified in th32ProcessID in the snapshot. + TH32CS_SNAPMODULE32 uint32 = 0x00000010 // Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process. + TH32CS_SNAPPROCESS uint32 = 0x00000002 // Includes all processes in the system in the snapshot. + TH32CS_SNAPTHREAD uint32 = 0x00000004 // Includes all threads in the system in the snapshot. +) + +// ProcessEntry32 is an equivalent representation of PROCESSENTRY32 in the +// Windows API. It contains a process's information. Do not modify or reorder. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx +type ProcessEntry32 struct { + size uint32 + CntUsage uint32 + ProcessID uint32 + DefaultHeapID uintptr + ModuleID uint32 + CntThreads uint32 + ParentProcessID uint32 + PriorityClassBase int32 + Flags uint32 + exeFile [MAX_PATH]uint16 +} + +// ExeFile returns the name of the executable file for the process. It does +// not contain the full path. +func (p ProcessEntry32) ExeFile() string { + return syscall.UTF16ToString(p.exeFile[:]) +} + +func (p ProcessEntry32) String() string { + return fmt.Sprintf("{CntUsage:%v ProcessID:%v DefaultHeapID:%v ModuleID:%v "+ + "CntThreads:%v ParentProcessID:%v PriorityClassBase:%v Flags:%v ExeFile:%v", + p.CntUsage, p.ProcessID, p.DefaultHeapID, p.ModuleID, p.CntThreads, + p.ParentProcessID, p.PriorityClassBase, p.Flags, p.ExeFile()) +} + +// MemoryStatusEx is an equivalent representation of MEMORYSTATUSEX in the +// Windows API. It contains information about the current state of both physical +// and virtual memory, including extended memory. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770 +type MemoryStatusEx struct { + length uint32 + MemoryLoad uint32 + TotalPhys uint64 + AvailPhys uint64 + TotalPageFile uint64 + AvailPageFile uint64 + TotalVirtual uint64 + AvailVirtual uint64 + AvailExtendedVirtual uint64 +} + +// ProcessMemoryCountersEx is an equivalent representation of +// PROCESS_MEMORY_COUNTERS_EX in the Windows API. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx +type ProcessMemoryCountersEx struct { + cb uint32 + PageFaultCount uint32 + PeakWorkingSetSize uintptr + WorkingSetSize uintptr + QuotaPeakPagedPoolUsage uintptr + QuotaPagedPoolUsage uintptr + QuotaPeakNonPagedPoolUsage uintptr + QuotaNonPagedPoolUsage uintptr + PagefileUsage uintptr + PeakPagefileUsage uintptr + PrivateUsage uintptr +} + +// GetLogicalDriveStrings returns a list of drives in the system. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364975(v=vs.85).aspx +func GetLogicalDriveStrings() ([]string, error) { + // Determine the size of the buffer required to receive all drives. + bufferLength, err := _GetLogicalDriveStringsW(0, nil) + if err != nil { + return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed to get buffer length") + } + if bufferLength < 0 { + return nil, errors.New("GetLogicalDriveStringsW returned an invalid buffer length") + } + + buffer := make([]uint16, bufferLength) + _, err = _GetLogicalDriveStringsW(uint32(len(buffer)), &buffer[0]) + if err != nil { + return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed") + } + + // Split the uint16 slice at null-terminators. + var startIdx int + var drivesUTF16 [][]uint16 + for i, value := range buffer { + if value == 0 { + drivesUTF16 = append(drivesUTF16, buffer[startIdx:i]) + startIdx = i + 1 + } + } + + // Convert the utf16 slices to strings. + drives := make([]string, 0, len(drivesUTF16)) + for _, driveUTF16 := range drivesUTF16 { + if len(driveUTF16) > 0 { + drives = append(drives, syscall.UTF16ToString(driveUTF16)) + } + } + + return drives, nil +} + +// GlobalMemoryStatusEx retrieves information about the system's current usage +// of both physical and virtual memory. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx +func GlobalMemoryStatusEx() (MemoryStatusEx, error) { + memoryStatusEx := MemoryStatusEx{length: sizeofMemoryStatusEx} + err := _GlobalMemoryStatusEx(&memoryStatusEx) + if err != nil { + return MemoryStatusEx{}, errors.Wrap(err, "GlobalMemoryStatusEx failed") + } + + return memoryStatusEx, nil +} + +// GetProcessMemoryInfo retrieves information about the memory usage of the +// specified process. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219(v=vs.85).aspx +func GetProcessMemoryInfo(handle syscall.Handle) (ProcessMemoryCountersEx, error) { + processMemoryCountersEx := ProcessMemoryCountersEx{cb: sizeofProcessMemoryCountersEx} + err := _GetProcessMemoryInfo(handle, &processMemoryCountersEx, processMemoryCountersEx.cb) + if err != nil { + return ProcessMemoryCountersEx{}, errors.Wrap(err, "GetProcessMemoryInfo failed") + } + + return processMemoryCountersEx, nil +} + +// GetProcessImageFileName Retrieves the name of the executable file for the +// specified process. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx +func GetProcessImageFileName(handle syscall.Handle) (string, error) { + buffer := make([]uint16, MAX_PATH) + _, err := _GetProcessImageFileName(handle, &buffer[0], uint32(len(buffer))) + if err != nil { + return "", errors.Wrap(err, "GetProcessImageFileName failed") + } + + return syscall.UTF16ToString(buffer), nil +} + +// GetSystemTimes retrieves system timing information. On a multiprocessor +// system, the values returned are the sum of the designated times across all +// processors. The returned kernel time does not include the system idle time. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx +func GetSystemTimes() (idle, kernel, user time.Duration, err error) { + var idleTime, kernelTime, userTime syscall.Filetime + err = _GetSystemTimes(&idleTime, &kernelTime, &userTime) + if err != nil { + return 0, 0, 0, errors.Wrap(err, "GetSystemTimes failed") + } + + idle = FiletimeToDuration(&idleTime) + kernel = FiletimeToDuration(&kernelTime) // Kernel time includes idle time so we subtract it out. + user = FiletimeToDuration(&userTime) + + return idle, kernel - idle, user, nil +} + +// FiletimeToDuration converts a Filetime to a time.Duration. Do not use this +// method to convert a Filetime to an actual clock time, for that use +// Filetime.Nanosecond(). +func FiletimeToDuration(ft *syscall.Filetime) time.Duration { + n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals + return time.Duration(n * 100) +} + +// GetDriveType Determines whether a disk drive is a removable, fixed, CD-ROM, +// RAM disk, or network drive. A trailing backslash is required on the +// rootPathName. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939 +func GetDriveType(rootPathName string) (DriveType, error) { + rootPathNamePtr, err := syscall.UTF16PtrFromString(rootPathName) + if err != nil { + return DRIVE_UNKNOWN, errors.Wrapf(err, "UTF16PtrFromString failed for rootPathName=%v", rootPathName) + } + + dt, err := _GetDriveType(rootPathNamePtr) + if err != nil { + return DRIVE_UNKNOWN, errors.Wrapf(err, "GetDriveType failed for rootPathName=%v", rootPathName) + } + + return dt, nil +} + +// EnumProcesses retrieves the process identifier for each process object in the +// system. This function can return a max of 65536 PIDs. If there are more +// processes than that then this will not return them all. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682629(v=vs.85).aspx +func EnumProcesses() ([]uint32, error) { + enumProcesses := func(size int) ([]uint32, error) { + var ( + pids = make([]uint32, size) + sizeBytes = len(pids) * sizeofUint32 + bytesWritten uint32 + ) + + err := _EnumProcesses(&pids[0], uint32(sizeBytes), &bytesWritten) + + pidsWritten := int(bytesWritten) / sizeofUint32 + if int(bytesWritten)%sizeofUint32 != 0 || pidsWritten > len(pids) { + return nil, errors.Errorf("EnumProcesses returned an invalid bytesWritten value of %v", bytesWritten) + } + pids = pids[:pidsWritten] + + return pids, err + } + + // Retry the EnumProcesses call with larger arrays if needed. + size := 2048 + var pids []uint32 + for tries := 0; tries < 5; tries++ { + var err error + pids, err = enumProcesses(size) + if err != nil { + return nil, errors.Wrap(err, "EnumProcesses failed") + } + + if len(pids) < size { + break + } + + // Increase the size the pids array and retry the enumProcesses call + // because the array wasn't large enough to hold all of the processes. + size *= 2 + } + + return pids, nil +} + +// GetDiskFreeSpaceEx retrieves information about the amount of space that is +// available on a disk volume, which is the total amount of space, the total +// amount of free space, and the total amount of free space available to the +// user that is associated with the calling thread. +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx +func GetDiskFreeSpaceEx(directoryName string) (freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64, err error) { + directoryNamePtr, err := syscall.UTF16PtrFromString(directoryName) + if err != nil { + return 0, 0, 0, errors.Wrapf(err, "UTF16PtrFromString failed for directoryName=%v", directoryName) + } + + err = _GetDiskFreeSpaceEx(directoryNamePtr, &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes) + if err != nil { + return 0, 0, 0, err + } + + return freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, nil +} + +// CreateToolhelp32Snapshot takes a snapshot of the specified processes, as well +// as the heaps, modules, and threads used by these processes. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx +func CreateToolhelp32Snapshot(flags, pid uint32) (syscall.Handle, error) { + h, err := _CreateToolhelp32Snapshot(flags, pid) + if err != nil { + return syscall.InvalidHandle, err + } + if h == syscall.InvalidHandle { + return syscall.InvalidHandle, syscall.GetLastError() + } + + return h, nil +} + +// Process32First retrieves information about the first process encountered in a +// system snapshot. +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834 +func Process32First(handle syscall.Handle) (ProcessEntry32, error) { + processEntry32 := ProcessEntry32{size: sizeofProcessEntry32} + err := _Process32First(handle, &processEntry32) + if err != nil { + return ProcessEntry32{}, errors.Wrap(err, "Process32First failed") + } + + return processEntry32, nil +} + +// Process32Next retrieves information about the next process recorded in a +// system snapshot. When there are no more processes to iterate then +// syscall.ERROR_NO_MORE_FILES is returned (use errors.Cause() to unwrap). +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684836 +func Process32Next(handle syscall.Handle) (ProcessEntry32, error) { + processEntry32 := ProcessEntry32{size: sizeofProcessEntry32} + err := _Process32Next(handle, &processEntry32) + if err != nil { + return ProcessEntry32{}, errors.Wrap(err, "Process32Next failed") + } + + return processEntry32, nil +} + +// Use "GOOS=windows go generate -v -x ." to generate the source. + +// Add -trace to enable debug prints around syscalls. +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go + +// Windows API calls +//sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx +//sys _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) = kernel32.GetLogicalDriveStringsW +//sys _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) = psapi.GetProcessMemoryInfo +//sys _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) = psapi.GetProcessImageFileNameW +//sys _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) = kernel32.GetSystemTimes +//sys _GetDriveType(rootPathName *uint16) (dt DriveType, err error) = kernel32.GetDriveTypeW +//sys _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses +//sys _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = kernel32.GetDiskFreeSpaceExW +//sys _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32FirstW +//sys _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32NextW +//sys _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) = kernel32.CreateToolhelp32Snapshot +//sys _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQuerySystemInformation +//sys _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQueryInformationProcess +//sys _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW +//sys _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) = advapi32.LookupPrivilegeValueW +//sys _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges diff --git a/vendor/github.com/elastic/gosigar/sys/windows/version.go b/vendor/github.com/elastic/gosigar/sys/windows/version.go new file mode 100644 index 000000000..d0bca89c1 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/version.go @@ -0,0 +1,43 @@ +// +build windows + +package windows + +import ( + "fmt" + "syscall" +) + +// Version identifies a Windows version by major, minor, and build number. +type Version struct { + Major int + Minor int + Build int +} + +// GetWindowsVersion returns the Windows version information. Applications not +// manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version +// value (6.2). +// +// For a table of version numbers see: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx +func GetWindowsVersion() Version { + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx + ver, err := syscall.GetVersion() + if err != nil { + // GetVersion should never return an error. + panic(fmt.Errorf("GetVersion failed: %v", err)) + } + + return Version{ + Major: int(ver & 0xFF), + Minor: int(ver >> 8 & 0xFF), + Build: int(ver >> 16), + } +} + +// IsWindowsVistaOrGreater returns true if the Windows version is Vista or +// greater. +func (v Version) IsWindowsVistaOrGreater() bool { + // Vista is 6.0. + return v.Major >= 6 && v.Minor >= 0 +} diff --git a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go new file mode 100644 index 000000000..53fae4e3b --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go @@ -0,0 +1,260 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package windows + +import "unsafe" +import "syscall" + +var _ unsafe.Pointer + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + modpsapi = syscall.NewLazyDLL("psapi.dll") + modntdll = syscall.NewLazyDLL("ntdll.dll") + modadvapi32 = syscall.NewLazyDLL("advapi32.dll") + + procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx") + procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") + procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW") + procGetSystemTimes = modkernel32.NewProc("GetSystemTimes") + procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") + procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") + procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") +) + +func _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) { + r1, _, e1 := syscall.Syscall(procGlobalMemoryStatusEx.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0) + length = uint32(r0) + if length == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(psmemCounters)), uintptr(cb)) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetProcessImageFileNameW.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(outImageFileName)), uintptr(size)) + length = uint32(r0) + if length == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) { + r1, _, e1 := syscall.Syscall(procGetSystemTimes.Addr(), 3, uintptr(unsafe.Pointer(idleTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetDriveType(rootPathName *uint16) (dt DriveType, err error) { + r0, _, e1 := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) + dt = DriveType(r0) + if dt == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(processIds)), uintptr(sizeBytes), uintptr(unsafe.Pointer(bytesReturned))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { + r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailable)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processID), 0) + handle = syscall.Handle(r0) + if handle == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) { + r0, _, e1 := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInformationClass), uintptr(unsafe.Pointer(systemInformation)), uintptr(systemInformationLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) + ntstatus = uint32(r0) + if ntstatus == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) { + r0, _, e1 := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(processHandle), uintptr(processInformationClass), uintptr(unsafe.Pointer(processInformation)), uintptr(processInformationLength), uintptr(unsafe.Pointer(returnLength)), 0) + ntstatus = uint32(r0) + if ntstatus == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return __LookupPrivilegeName(_p0, luid, buffer, size) +} + +func __LookupPrivilegeName(systemName *uint16, luid *int64, buffer *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + var _p1 *uint16 + _p1, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return __LookupPrivilegeValue(_p0, _p1, luid) +} + +func __LookupPrivilegeValue(systemName *uint16, name *uint16, luid *int64) (err error) { + r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { + var _p0 uint32 + if releaseAll { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) + success = r0 != 0 + if true { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/github.com/ethereum/go-ethereum/.dockerignore b/vendor/github.com/ethereum/go-ethereum/.dockerignore index d280741c6..0c013d18b 100644 --- a/vendor/github.com/ethereum/go-ethereum/.dockerignore +++ b/vendor/github.com/ethereum/go-ethereum/.dockerignore @@ -1,7 +1,3 @@ -**/.git -.git -!.git/HEAD -!.git/refs/heads **/*_test.go build/_workspace diff --git a/vendor/github.com/ethereum/go-ethereum/.gitignore b/vendor/github.com/ethereum/go-ethereum/.gitignore index 3e0009e16..3016facee 100644 --- a/vendor/github.com/ethereum/go-ethereum/.gitignore +++ b/vendor/github.com/ethereum/go-ethereum/.gitignore @@ -42,6 +42,7 @@ profile.cov /dashboard/assets/node_modules /dashboard/assets/stats.json /dashboard/assets/bundle.js +/dashboard/assets/bundle.js.map /dashboard/assets/package-lock.json **/yarn-error.log diff --git a/vendor/github.com/ethereum/go-ethereum/.travis.yml b/vendor/github.com/ethereum/go-ethereum/.travis.yml index d93282078..996ec4fdc 100644 --- a/vendor/github.com/ethereum/go-ethereum/.travis.yml +++ b/vendor/github.com/ethereum/go-ethereum/.travis.yml @@ -1,33 +1,48 @@ language: go go_import_path: github.com/ethereum/go-ethereum sudo: false -matrix: +jobs: include: - - os: linux + # This builder only tests code linters on latest version of Go + - stage: lint + os: linux dist: xenial - sudo: required - go: 1.10.x + go: 1.12.x + env: + - lint + git: + submodules: false # avoid cloning ethereum/tests script: - - sudo modprobe fuse - - sudo chmod 666 /dev/fuse - - sudo chown root:$USER /etc/fuse.conf - - go run build/ci.go install - - go run build/ci.go test -coverage $TEST_PACKAGES + - go run build/ci.go lint - # These are the latest Go versions. - - os: linux + - stage: build + os: linux dist: xenial - sudo: required go: 1.11.x script: - - sudo modprobe fuse - - sudo chmod 666 /dev/fuse - - sudo chown root:$USER /etc/fuse.conf - go run build/ci.go install - go run build/ci.go test -coverage $TEST_PACKAGES - - os: osx - go: 1.11.x + - stage: build + os: linux + dist: xenial + go: 1.12.x + script: + - go run build/ci.go install + - go run build/ci.go test -coverage $TEST_PACKAGES + + # These are the latest Go versions. + - stage: build + os: linux + dist: xenial + go: 1.13.x + script: + - go run build/ci.go install + - go run build/ci.go test -coverage $TEST_PACKAGES + + - stage: build + os: osx + go: 1.13.x script: - echo "Increase the maximum number of open file descriptors on macOS" - NOFILE=20480 @@ -41,22 +56,12 @@ matrix: - go run build/ci.go install - go run build/ci.go test -coverage $TEST_PACKAGES - # This builder only tests code linters on latest version of Go - - os: linux - dist: xenial - go: 1.11.x - env: - - lint - git: - submodules: false # avoid cloning ethereum/tests - script: - - go run build/ci.go lint - # This builder does the Ubuntu PPA upload - - if: type = push + - stage: build + if: type = push os: linux dist: xenial - go: 1.11.x + go: 1.13.x env: - ubuntu-ppa git: @@ -75,11 +80,12 @@ matrix: - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " # This builder does the Linux Azure uploads - - if: type = push + - stage: build + if: type = push os: linux dist: xenial sudo: required - go: 1.11.x + go: 1.13.x env: - azure-linux git: @@ -109,12 +115,13 @@ matrix: - 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 - - if: type = push + - stage: build + if: type = push os: linux dist: xenial services: - docker - go: 1.11.x + go: 1.13.x env: - azure-linux-mips git: @@ -137,7 +144,8 @@ matrix: - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds # This builder does the Android Maven and Azure uploads - - if: type = push + - stage: build + if: type = push os: linux dist: xenial addons: @@ -159,25 +167,25 @@ matrix: git: submodules: false # avoid cloning ethereum/tests before_install: - - curl https://storage.googleapis.com/golang/go1.11.5.linux-amd64.tar.gz | tar -xz + - curl https://dl.google.com/go/go1.13.linux-amd64.tar.gz | tar -xz - export PATH=`pwd`/go/bin:$PATH - export GOROOT=`pwd`/go - export GOPATH=$HOME/go script: # Build the Android archive and upload it to Maven Central and Azure - - curl https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip -o android-ndk-r17b.zip - - unzip -q android-ndk-r17b.zip && rm android-ndk-r17b.zip - - mv android-ndk-r17b $HOME - - export ANDROID_NDK=$HOME/android-ndk-r17b + - curl https://dl.google.com/android/repository/android-ndk-r19b-linux-x86_64.zip -o android-ndk-r19b.zip + - unzip -q android-ndk-r19b.zip && rm android-ndk-r19b.zip + - mv android-ndk-r19b $ANDROID_HOME/ndk-bundle - mkdir -p $GOPATH/src/github.com/ethereum - - ln -s `pwd` $GOPATH/src/github.com/ethereum + - ln -s `pwd` $GOPATH/src/github.com/ethereum/go-ethereum - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds # This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads - - if: type = push + - stage: build + if: type = push os: osx - go: 1.11.x + go: 1.13.x env: - azure-osx - azure-ios @@ -204,10 +212,11 @@ matrix: - 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 - - if: type = cron + - stage: build + if: type = cron os: linux dist: xenial - go: 1.11.x + go: 1.13.x env: - azure-purge git: diff --git a/vendor/github.com/ethereum/go-ethereum/AUTHORS b/vendor/github.com/ethereum/go-ethereum/AUTHORS index 609dc48c7..526ea35c2 100644 --- a/vendor/github.com/ethereum/go-ethereum/AUTHORS +++ b/vendor/github.com/ethereum/go-ethereum/AUTHORS @@ -1,5 +1,11 @@ # This is the official list of go-ethereum authors for copyright purposes. +a e r t h +Abel Nieto +Abel Nieto +Adam Babik +Aditya +Adrià Cidre Afri Schoedon <5chdn@users.noreply.github.com> Agustin Armellini Fischer Airead @@ -10,165 +16,354 @@ Alex Leverington Alex Wu Alexandre Van de Sande Ali Hajimirza +am2rican5 +Andrea Franz +Andrey Petrov +Andrey Petrov +ANOTHEL +Antoine Rondelet Anton Evangelatov +Antonio Salazar Cardozo Arba Sasmoyo Armani Ferrante Armin Braun Aron Fischer +atsushi-ishibashi +ayeowch +b00ris +bailantaotao +baizhenxuan +Balint Gabor Bas van Kervel Benjamin Brent +benma Benoit Verkindt +bloonfield Bo Bo Ye Bob Glickstein +Brent Brian Schroeder +Bruno Škvorc +C. Brown +Caesar Chad Casey Detrio +CDsigma +changhong Chase Wright +Chen Quan +chenyufeng +Christian Muehlhaeuser Christoph Jentzsch +cong +Corey Lin <514971757@qq.com> +cpusoft +Crispin Flowerday +croath +cui <523516579@qq.com> +Dan Kinsley Daniel A. Nagy Daniel Sloof Darrel Herbst Dave Appleton +Dave McGregor +David Huie +Derek Gottfrid Diego Siqueira +Diep Pham +dipingxian2 <39109351+dipingxian2@users.noreply.github.com> +dm4 +Dmitrij Koniajev Dmitry Shulyak +Domino Valdano +Domino Valdano +Dragan Milic +dragonvslinux <35779158+dragononcrypto@users.noreply.github.com> Egon Elbre +Elad +Eli Elias Naur Elliot Shepherd +Emil +emile Enrique Fynn +Enrique Fynn +EOS Classic +Erichin Ernesto del Toro Ethan Buchman +ethersphere Eugene Valeyev Evangelos Pappas +Evgeny Evgeny Danilenko <6655321@bk.ru> +evgk Fabian Vogelsteller Fabio Barone Fabio Berger FaceHo Felix Lange +Ferenc Szabo +ferhat elmas Fiisio +Frank Szendzielarz <33515470+FrankSzendzielarz@users.noreply.github.com> Frank Wang +Franklin Furkan KAMACI +GagziW Gary Rong George Ornbo Gregg Dourgarian +Guilherme Salgado Guillaume Ballet Guillaume Nicolas +GuiltyMorishita +Gus Gustav Simonsson +Gísli Kristjánsson +Ha ĐANG +HackyMiner +hadv Hao Bryan Cheng +HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Henning Diedrich +holisticode +Hongbin Mao +Hsien-Tang Kao +Husam Ibrahim <39692071+HusamIbrahim@users.noreply.github.com> +hydai +Hyung-Kyu Hqueue Choi +Ian Macalinao +Ian Norden Isidoro Ghezzi +Iskander (Alex) Sharipov Ivan Daniluk +Ivo Georgiev Jae Kwon Jamie Pitts +Janos Guljas Janoš Guljaš Jason Carver +Javier Peletier +Javier Peletier +Javier Sagredo +Jay Jay Guo +Jaynti Kanani +Jeff Prestes Jeff R. Allen +Jeffery Robert Walsh Jeffrey Wilcke Jens Agerberg +Jeremy McNevin +Jeremy Schlatter +Jerzy Lasyk Jia Chenhui Jim McDonald +jkcomment Joel Burget +John C. Vernaleo +Johns Beharry +Jonas Jonathan Brown +JoranHonig +Jordan Krage Joseph Chow +jtakalai +JU HYEONG PARK Justin Clark-Casey Justin Drake +jwasinger +ken10100147 Kenji Siu +Kenso Trabing +Kenso Trabing +Kevin +kevin.xu +kiel barry +kimmylin <30611210+kimmylin@users.noreply.github.com> +Kitten King <53072918+kittenking@users.noreply.github.com> +knarfeh Kobi Gurkan Konrad Feldmeier +Kris Shinn Kurkó Mihály +Kushagra Sharma +Kwuaint <34888408+kwuaint@users.noreply.github.com> Kyuntae Ethan Kim +ledgerwatch Lefteris Karapetsas Leif Jurvetson Leo Shklovskii +LeoLiao Lewis Marshall +lhendre +Liang Ma +Liang Ma +Liang ZOU +libotony +ligi Lio李欧 +Lorenzo Manacorda Louis Holbrook Luca Zeug Magicking +manlio Maran Hidskes Marek Kotewicz +Marius van der Wijden Mark +Mark Rushakoff +mark.lin +Martin Alex Philip Dawson Martin Holst Swende +Martin Klepsch +Mats Julian Olsen +Matt K <1036969+mkrump@users.noreply.github.com> Matthew Di Ferrante +Matthew Halpern +Matthew Halpern Matthew Wampler-Doty +Max Sistemich Maximilian Meister Micah Zoltu Michael Ruminer Miguel Mota Miya Chen +Mohanson +mr_franklin +Mymskmkt <1847234666@qq.com> +Nalin Bhardwaj Nchinda Nchinda +necaremus +needkane <604476380@qq.com> +Nguyen Kien Trung +Nguyen Sy Thanh Son Nick Dodson Nick Johnson Nicolas Guillaume +Nilesh Trivedi +Nimrod Gutman +njupt-moon <1015041018@njupt.edu.cn> +nkbai +nobody Noman +Oleg Kovalov Oli Bye +Osuke +Paul Berg Paul Litvak Paulo L F Casaretto Paweł Bylica +Pedro Pombeiro +Peter Broadhurst Peter Pratscher Petr Mikusek +Philip Schlump +Pierre Neter +PilkyuJung +protolambda Péter Szilágyi -RJ Catalano +qd-ethan <31876119+qdgogogo@users.noreply.github.com> +Raghav Sood +Ralph Caraveo +Ralph Caraveo III Ramesh Nair +reinerRubin +rhaps107 Ricardo Catalinas Jiménez Ricardo Domingos Richard Hart +RJ Catalano Rob +Rob Mulholand Robert Zaremba +Roc Yu +Runchao Han Russ Cox +Ryan Schneider Rémy Roy S. Matthew English +salanfe +Samuel Marks +Sarlor +Sasuke1964 +Saulius Grigaitis +Sean +Sheldon <11510383@mail.sustc.edu.cn> +Sheldon <374662347@qq.com> Shintaro Kaneko +Shuai Qi +Shunsuke Watanabe +silence +Simon Jentzsch +slumber1122 +Smilenator Sorin Neacsu Stein Dekker +Steve Gattuso +Steve Ruckdashel Steve Waldman Steven Roose +stompesi +stormpang +sunxiaojun2014 +tamirms Taylor Gerring +TColl <38299499+TColl@users.noreply.github.com> +terasum Thomas Bocek +thomasmodeneis +thumb8432 Ti Zhou Tosh Camille +tsarpaul +tzapu +ult-bobonovski Valentin Wüstholz +Vedhavyas Singareddi Victor Farazdagi Victor Tran +Vie Viktor Trón Ville Sundell +vim88 Vincent G +Vincent Serpoul Vitalik Buterin +Vitaly Bogdanov Vitaly V Vivek Anand +Vlad +Vlad Bokov Vlad Gluhovsky +weimumu <934657014@qq.com> +Wenbiao Zheng +William Setzer +williambannas +Wuxiang +xiekeyang +xincaosu +yahtoo +YaoZengzeng +YH-Zhou Yohann Léon Yoichi Hirai Yondon Fu +YOSHIDA Masanori +yoza +Yusup Zach +zah Zahoor Mohamed +Zak Cole +zer0to0ne <36526113+zer0to0ne@users.noreply.github.com> +Zhenguo Niu 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 +Łukasz Kurowski ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com> Максим Чусовлянов -Ralph Caraveo +大彬 +贺鹏飞 +유용환 <33824408+eric-yoo@users.noreply.github.com> diff --git a/vendor/github.com/ethereum/go-ethereum/Dockerfile b/vendor/github.com/ethereum/go-ethereum/Dockerfile index e87dd35d3..114e76205 100644 --- a/vendor/github.com/ethereum/go-ethereum/Dockerfile +++ b/vendor/github.com/ethereum/go-ethereum/Dockerfile @@ -1,7 +1,7 @@ # Build Geth in a stock Go builder container -FROM golang:1.11-alpine as builder +FROM golang:1.13-alpine as builder -RUN apk add --no-cache make gcc musl-dev linux-headers +RUN apk add --no-cache make gcc musl-dev linux-headers git ADD . /go-ethereum RUN cd /go-ethereum && make geth @@ -12,5 +12,5 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/ -EXPOSE 8545 8546 30303 30303/udp +EXPOSE 8545 8546 8547 30303 30303/udp ENTRYPOINT ["geth"] diff --git a/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools b/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools index e984a1b09..2f661ba01 100644 --- a/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools +++ b/vendor/github.com/ethereum/go-ethereum/Dockerfile.alltools @@ -1,7 +1,7 @@ # Build Geth in a stock Go builder container -FROM golang:1.11-alpine as builder +FROM golang:1.13-alpine as builder -RUN apk add --no-cache make gcc musl-dev linux-headers +RUN apk add --no-cache make gcc musl-dev linux-headers git ADD . /go-ethereum RUN cd /go-ethereum && make all @@ -12,4 +12,4 @@ FROM alpine:latest RUN apk add --no-cache ca-certificates COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/ -EXPOSE 8545 8546 30303 30303/udp +EXPOSE 8545 8546 8547 30303 30303/udp diff --git a/vendor/github.com/ethereum/go-ethereum/Makefile b/vendor/github.com/ethereum/go-ethereum/Makefile index 966bf9cbb..5d4a82de8 100644 --- a/vendor/github.com/ethereum/go-ethereum/Makefile +++ b/vendor/github.com/ethereum/go-ethereum/Makefile @@ -2,13 +2,13 @@ # with Go source code. If you know what GOPATH is then you probably # don't need to bother with make. -.PHONY: geth android ios geth-cross swarm evm all test clean +.PHONY: geth android ios geth-cross evm all test clean .PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le .PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 .PHONY: geth-windows geth-windows-386 geth-windows-amd64 -GOBIN = $(shell pwd)/build/bin +GOBIN = ./build/bin GO ?= latest geth: @@ -16,11 +16,6 @@ geth: @echo "Done building." @echo "Run \"$(GOBIN)/geth\" to launch geth." -swarm: - build/env.sh go run build/ci.go install ./cmd/swarm - @echo "Done building." - @echo "Run \"$(GOBIN)/swarm\" to launch swarm." - all: build/env.sh go run build/ci.go install @@ -57,9 +52,6 @@ devtools: @type "solc" 2> /dev/null || echo 'Please install solc' @type "protoc" 2> /dev/null || echo 'Please install protoc' -swarm-devtools: - env GOBIN= go install ./cmd/swarm/mimegen - # Cross Compilation Targets (xgo) geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios diff --git a/vendor/github.com/ethereum/go-ethereum/README.md b/vendor/github.com/ethereum/go-ethereum/README.md index 7593dd090..3bfd24906 100644 --- a/vendor/github.com/ethereum/go-ethereum/README.md +++ b/vendor/github.com/ethereum/go-ethereum/README.md @@ -1,6 +1,6 @@ ## Go Ethereum -Official golang implementation of the Ethereum protocol. +Official Golang implementation of the Ethereum protocol. [![API Reference]( https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 @@ -9,303 +9,340 @@ https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/6874 [![Travis](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum) [![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv) -Automated builds are available for stable releases and the unstable master branch. -Binary archives are published at https://geth.ethereum.org/downloads/. +Automated builds are available for stable releases and the unstable master branch. Binary +archives are published at https://geth.ethereum.org/downloads/. ## Building the source -For prerequisites and detailed build instructions please read the -[Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) -on the wiki. +For prerequisites and detailed build instructions please read the [Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) on the wiki. -Building geth requires both a Go (version 1.9 or later) and a C compiler. -You can install them using your favourite package manager. -Once the dependencies are installed, run +Building `geth` requires both a Go (version 1.10 or later) and a C compiler. You can install +them using your favourite package manager. Once the dependencies are installed, run - make geth +```shell +make geth +``` or, to build the full suite of utilities: - make all +```shell +make all +``` ## Executables -The go-ethereum project comes with several wrappers/executables found in the `cmd` directory. +The go-ethereum project comes with several wrappers/executables found in the `cmd` +directory. -| Command | Description | -|:----------:|-------------| -| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options) for command line options. | -| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) with expanded functionality if the contract bytecode is also available. However it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) wiki page for details. | -| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | -| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). | -| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/ethereum/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/ethereum/rpc-tests/blob/master/README.md) for details. | -| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereum/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | -| `swarm` | Swarm daemon and tools. This is the entrypoint for the Swarm network. `swarm --help` for command line options and subcommands. See [Swarm README](https://github.com/ethereum/go-ethereum/tree/master/swarm) for more information. | -| `puppeth` | a CLI wizard that aids in creating a new Ethereum network. | +| Command | Description | +| :-----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options) for command line options. | +| `abigen` | Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) wiki page for details. | +| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | +| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). | +| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/ethereum/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/ethereum/rpc-tests/blob/master/README.md) for details. | +| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereum/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | +| `puppeth` | a CLI wizard that aids in creating a new Ethereum network. | -## Running geth +## Running `geth` Going through all the possible command line flags is out of scope here (please consult our -[CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)), but we've -enumerated a few common parameter combos to get you up to speed quickly on how you can run your -own Geth instance. +[CLI Wiki page](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)), +but we've enumerated a few common parameter combos to get you up to speed quickly +on how you can run your own `geth` instance. ### Full node on the main Ethereum network -By far the most common scenario is people wanting to simply interact with the Ethereum network: -create accounts; transfer funds; deploy and interact with contracts. For this particular use-case -the user doesn't care about years-old historical data, so we can fast-sync quickly to the current -state of the network. To do so: +By far the most common scenario is people wanting to simply interact with the Ethereum +network: create accounts; transfer funds; deploy and interact with contracts. For this +particular use-case the user doesn't care about years-old historical data, so we can +fast-sync quickly to the current state of the network. To do so: -``` +```shell $ geth console ``` This command will: - - * 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), + * 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). - This tool is optional and if you leave it out you can always attach to an already running Geth instance - with `geth attach`. + as well as `geth`'s own [management APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs). + This tool is optional and if you leave it out you can always attach to an already running + `geth` instance with `geth attach`. -### Full node on the Ethereum test network +### A Full node on the Ethereum test network -Transitioning towards developers, if you'd like to play around with creating Ethereum contracts, you -almost certainly would like to do that without any real money involved until you get the hang of the -entire system. In other words, instead of attaching to the main network, you want to join the **test** -network with your node, which is fully equivalent to the main network, but with play-Ether only. +Transitioning towards developers, if you'd like to play around with creating Ethereum +contracts, you almost certainly would like to do that without any real money involved until +you get the hang of the entire system. In other words, instead of attaching to the main +network, you want to join the **test** network with your node, which is fully equivalent to +the main network, but with play-Ether only. -``` +```shell $ geth --testnet console ``` -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. +The `console` subcommand has 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 here. -Specifying the `--testnet` flag however will reconfigure your Geth instance a bit: +Specifying the `--testnet` flag, however, will reconfigure your `geth` instance a bit: - * Instead of using the default data directory (`~/.ethereum` on Linux for example), Geth will nest - itself one level deeper into a `testnet` subfolder (`~/.ethereum/testnet` on Linux). Note, on OSX - and Linux this also means that attaching to a running testnet node requires the use of a custom - endpoint since `geth attach` will try to attach to a production node endpoint by default. E.g. - `geth attach /testnet/geth.ipc`. Windows users are not affected by this. - * Instead of connecting the main Ethereum network, the client will connect to the test network, - which uses different P2P bootnodes, different network IDs and genesis states. - -*Note: Although there are some internal protective measures to prevent transactions from crossing -over between the main network and test network, you should make sure to always use separate accounts -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.* + * Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth` + will nest itself one level deeper into a `testnet` subfolder (`~/.ethereum/testnet` on + Linux). Note, on OSX and Linux this also means that attaching to a running testnet node + requires the use of a custom endpoint since `geth attach` will try to attach to a + production node endpoint by default. E.g. + `geth attach /testnet/geth.ipc`. Windows users are not affected by + this. + * Instead of connecting the main Ethereum network, the client will connect to the test + network, which uses different P2P bootnodes, different network IDs and genesis states. + +*Note: Although there are some internal protective measures to prevent transactions from +crossing over between the main network and test network, you should make sure to always +use separate accounts 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. +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. -``` +```shell $ geth --rinkeby console ``` ### Configuration -As an alternative to passing the numerous flags to the `geth` binary, you can also pass a configuration file via: +As an alternative to passing the numerous flags to the `geth` binary, you can also pass a +configuration file via: -``` +```shell $ geth --config /path/to/your_config.toml ``` -To get an idea how the file should look like you can use the `dumpconfig` subcommand to export your existing configuration: +To get an idea how the file should look like you can use the `dumpconfig` subcommand to +export your existing configuration: -``` +```shell $ geth --your-favourite-flags dumpconfig ``` -*Note: This works only with geth v1.6.0 and above.* +*Note: This works only with `geth` v1.6.0 and above.* #### Docker quick start -One of the quickest ways to get Ethereum up and running on your machine is by using Docker: +One of the quickest ways to get Ethereum up and running on your machine is by using +Docker: -``` +```shell docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \ -p 8545:8545 -p 30303:30303 \ ethereum/client-go ``` -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. +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. +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. -### Programatically interfacing Geth nodes +### Programmatically interfacing `geth` nodes -As a developer, sooner rather than later you'll want to start interacting with Geth and the Ethereum -network via your own programs and not manually through the console. To aid this, Geth has built-in -support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC) and -[Geth specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)). These can be -exposed via HTTP, WebSockets and IPC (unix sockets on unix based platforms, and named pipes on Windows). +As a developer, sooner rather than later you'll want to start interacting with `geth` and the +Ethereum network via your own programs and not manually through the console. To aid +this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://github.com/ethereum/wiki/wiki/JSON-RPC) +and [`geth` specific APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)). +These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based +platforms, and named pipes on Windows). -The IPC interface is enabled by default and exposes all the APIs supported by Geth, whereas the HTTP -and WS interfaces need to manually be enabled and only expose a subset of APIs due to security reasons. -These can be turned on/off and configured as you'd expect. +The IPC interface is enabled by default and exposes all the APIs supported by `geth`, +whereas the HTTP and WS interfaces need to manually be enabled and only expose a +subset of APIs due to security reasons. These can be turned on/off and configured as +you'd expect. HTTP based JSON-RPC API options: * `--rpc` Enable the HTTP-RPC server - * `--rpcaddr` HTTP-RPC server listening interface (default: "localhost") - * `--rpcport` HTTP-RPC server listening port (default: 8545) - * `--rpcapi` API's offered over the HTTP-RPC interface (default: "eth,net,web3") + * `--rpcaddr` HTTP-RPC server listening interface (default: `localhost`) + * `--rpcport` HTTP-RPC server listening port (default: `8545`) + * `--rpcapi` API's offered over the HTTP-RPC interface (default: `eth,net,web3`) * `--rpccorsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced) * `--ws` Enable the WS-RPC server - * `--wsaddr` WS-RPC server listening interface (default: "localhost") - * `--wsport` WS-RPC server listening port (default: 8546) - * `--wsapi` API's offered over the WS-RPC interface (default: "eth,net,web3") + * `--wsaddr` WS-RPC server listening interface (default: `localhost`) + * `--wsport` WS-RPC server listening port (default: `8546`) + * `--wsapi` API's offered over the WS-RPC interface (default: `eth,net,web3`) * `--wsorigins` Origins from which to accept websockets requests * `--ipcdisable` Disable the IPC-RPC server - * `--ipcapi` API's offered over the IPC-RPC interface (default: "admin,debug,eth,miner,net,personal,shh,txpool,web3") + * `--ipcapi` API's offered over the IPC-RPC interface (default: `admin,debug,eth,miner,net,personal,shh,txpool,web3`) * `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it) -You'll need to use your own programming environments' capabilities (libraries, tools, etc) to connect -via HTTP, WS or IPC to a Geth node configured with the above flags and you'll need to speak [JSON-RPC](https://www.jsonrpc.org/specification) -on all transports. You can reuse the same connection for multiple requests! +You'll need to use your own programming environments' capabilities (libraries, tools, etc) to +connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll +need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You +can reuse the same connection for multiple requests! -**Note: Please understand the security implications of opening up an HTTP/WS based transport before -doing so! Hackers on the internet are actively trying to subvert Ethereum nodes with exposed APIs! -Further, all browser tabs can access locally running webservers, so malicious webpages could try to -subvert locally available APIs!** +**Note: Please understand the security implications of opening up an HTTP/WS based +transport before doing so! Hackers on the internet are actively trying to subvert +Ethereum nodes with exposed APIs! Further, all browser tabs can access locally +running web servers, so malicious web pages could try to subvert locally available +APIs!** ### Operating a private network -Maintaining your own private network is more involved as a lot of configurations taken for granted in -the official networks need to be manually set up. +Maintaining your own private network is more involved as a lot of configurations taken for +granted in the official networks need to be manually set up. #### Defining the private genesis state -First, you'll need to create the genesis state of your networks, which all nodes need to be aware of -and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`): +First, you'll need to create the genesis state of your networks, which all nodes need to be +aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`): ```json { "config": { - "chainId": 0, - "homesteadBlock": 0, - "eip155Block": 0, - "eip158Block": 0 - }, - "alloc" : {}, - "coinbase" : "0x0000000000000000000000000000000000000000", - "difficulty" : "0x20000", - "extraData" : "", - "gasLimit" : "0x2fefd8", - "nonce" : "0x0000000000000042", - "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp" : "0x00" + "chainId": , + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0 + }, + "alloc": {}, + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x20000", + "extraData": "", + "gasLimit": "0x2fefd8", + "nonce": "0x0000000000000042", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00" } ``` -The above fields should be fine for most purposes, although we'd recommend changing the `nonce` to -some random value so you prevent unknown remote nodes from being able to connect to you. If you'd -like to pre-fund some accounts for easier testing, you can populate the `alloc` field with account -configs: +The above fields should be fine for most purposes, although we'd recommend changing +the `nonce` to some random value so you prevent unknown remote nodes from being able +to connect to you. If you'd like to pre-fund some accounts for easier testing, create +the accounts and populate the `alloc` field with their addresses. ```json "alloc": { - "0x0000000000000000000000000000000000000001": {"balance": "111111111"}, - "0x0000000000000000000000000000000000000002": {"balance": "222222222"} + "0x0000000000000000000000000000000000000001": { + "balance": "111111111" + }, + "0x0000000000000000000000000000000000000002": { + "balance": "222222222" + } } ``` -With the genesis state defined in the above JSON file, you'll need to initialize **every** Geth node -with it prior to starting it up to ensure all blockchain parameters are correctly set: +With the genesis state defined in the above JSON file, you'll need to initialize **every** +`geth` node with it prior to starting it up to ensure all blockchain parameters are correctly +set: -``` +```shell $ geth init path/to/genesis.json ``` #### Creating the rendezvous point -With all nodes that you want to run initialized to the desired genesis state, you'll need to start a -bootstrap node that others can use to find each other in your network and/or over the internet. The -clean way is to configure and run a dedicated bootnode: +With all nodes that you want to run initialized to the desired genesis state, you'll need to +start a bootstrap node that others can use to find each other in your network and/or over +the internet. The clean way is to configure and run a dedicated bootnode: -``` +```shell $ bootnode --genkey=boot.key $ bootnode --nodekey=boot.key ``` With the bootnode online, it will display an [`enode` URL](https://github.com/ethereum/wiki/wiki/enode-url-format) -that other nodes can use to connect to it and exchange peer information. Make sure to replace the -displayed IP address information (most probably `[::]`) with your externally accessible IP to get the -actual `enode` URL. +that other nodes can use to connect to it and exchange peer information. Make sure to +replace the displayed IP address information (most probably `[::]`) with your externally +accessible IP to get the actual `enode` URL. -*Note: You could also use a full fledged Geth node as a bootnode, but it's the less recommended way.* +*Note: You could also use a full-fledged `geth` node as a bootnode, but it's the less +recommended way.* #### Starting up your member nodes -With the bootnode operational and externally reachable (you can try `telnet ` to ensure -it's indeed reachable), start every subsequent Geth node pointed to the bootnode for peer discovery -via the `--bootnodes` flag. It will probably also be desirable to keep the data directory of your -private network separated, so do also specify a custom `--datadir` flag. +With the bootnode operational and externally reachable (you can try +`telnet ` to ensure it's indeed reachable), start every subsequent `geth` +node pointed to the bootnode for peer discovery via the `--bootnodes` flag. It will +probably also be desirable to keep the data directory of your private network separated, so +do also specify a custom `--datadir` flag. -``` +```shell $ geth --datadir=path/to/custom/data/folder --bootnodes= ``` -*Note: Since your network will be completely cut off from the main and test networks, you'll also -need to configure a miner to process transactions and create new blocks for you.* +*Note: Since your network will be completely cut off from the main and test networks, you'll +also need to configure a miner to process transactions and create new blocks for you.* #### Running a private miner -Mining on the public Ethereum network is a complex task as it's only feasible using GPUs, requiring -an OpenCL or CUDA enabled `ethminer` instance. For information on such a setup, please consult the -[EtherMining subreddit](https://www.reddit.com/r/EtherMining/) and the [Genoil miner](https://github.com/Genoil/cpp-ethereum) -repository. +Mining on the public Ethereum network is a complex task as it's only feasible using GPUs, +requiring an OpenCL or CUDA enabled `ethminer` instance. For information on such a +setup, please consult the [EtherMining subreddit](https://www.reddit.com/r/EtherMining/) +and the [Genoil miner](https://github.com/Genoil/cpp-ethereum) repository. -In a private network setting however, a single CPU miner instance is more than enough for practical -purposes as it can produce a stable stream of blocks at the correct intervals without needing heavy -resources (consider running on a single thread, no need for multiple ones either). To start a Geth -instance for mining, run it with all your usual flags, extended by: +In a private network setting, however a single CPU miner instance is more than enough for +practical purposes as it can produce a stable stream of blocks at the correct intervals +without needing heavy resources (consider running on a single thread, no need for multiple +ones either). To start a `geth` instance for mining, run it with all your usual flags, extended +by: -``` +```shell $ geth --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000 ``` -Which will start mining blocks and transactions on a single CPU thread, crediting all proceedings to -the account specified by `--etherbase`. You can further tune the mining by changing the default gas -limit blocks converge to (`--targetgaslimit`) and the price transactions are accepted at (`--gasprice`). +Which will start mining blocks and transactions on a single CPU thread, crediting all +proceedings to the account specified by `--etherbase`. You can further tune the mining +by changing the default gas limit blocks converge to (`--targetgaslimit`) and the price +transactions are accepted at (`--gasprice`). ## Contribution -Thank you for considering to help out with the source code! We welcome contributions from -anyone on the internet, and are grateful for even the smallest of fixes! +Thank you for considering to help out with the source code! We welcome contributions +from anyone on the internet, and are grateful for even the smallest of fixes! If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request -for the maintainers to review and merge into the main code base. If you wish to submit more -complex changes though, please check up with the core devs first on [our gitter channel](https://gitter.im/ethereum/go-ethereum) -to ensure those changes are in line with the general philosophy of the project and/or get some -early feedback which can make both your efforts much lighter as well as our review and merge -procedures quick and simple. +for the maintainers to review and merge into the main code base. If you wish to submit +more complex changes though, please check up with the core devs first on [our gitter channel](https://gitter.im/ethereum/go-ethereum) +to ensure those changes are in line with the general philosophy of the project and/or get +some early feedback which can make both your efforts much lighter as well as our review +and merge procedures quick and simple. Please make sure your contributions adhere to our coding guidelines: - * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). - * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. + * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) + guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). + * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) + guidelines. * Pull requests need to be based on and opened against the `master` branch. * Commit messages should be prefixed with the package(s) they modify. * E.g. "eth, rpc: make trace configs optional" Please see the [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide) -for more details on configuring your environment, managing project dependencies and testing procedures. +for more details on configuring your environment, managing project dependencies, and +testing procedures. ## License The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the -[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html), also -included in our repository in the `COPYING.LESSER` file. +[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html), +also included in our repository in the `COPYING.LESSER` file. The go-ethereum binaries (i.e. all code inside of the `cmd` directory) is licensed under the -[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also included -in our repository in the `COPYING` file. +[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also +included in our repository in the `COPYING` file. diff --git a/vendor/github.com/ethereum/go-ethereum/SECURITY.md b/vendor/github.com/ethereum/go-ethereum/SECURITY.md new file mode 100644 index 000000000..bc54ede42 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/SECURITY.md @@ -0,0 +1,120 @@ +# Security Policy + +## Supported Versions + +Please see Releases. We recommend to use the most recent released version. + +## Audit reports + +Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits + + +| Scope | Date | Report Link | +| ------- | ------- | ----------- | +| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) | +| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) | + + + +## Reporting a Vulnerability + +**Please do not file a public ticket** mentioning the vulnerability. + +To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. + +The following key may be used to communicate sensitive information to developers. + +Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A` + + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaY +neAk3Bp182GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9 +L8c8yiqry1ZTCmYMqCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUi +m+y7buJDtoNf7YILlhDQXN8qlHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0b +fUo9pexOn7LS4SojoJmsm/5dp6AoKlac48cZU5zwR9AYcq/nvkrfmf2WkObg/xRd +EvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/yPFE335k+ujjZCPOu7OwjzDk7 +M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXChoyI8vbfp4dGvCvYqv +QAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+FnQOUgg2H +h8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c +2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZ +EZCjMXxB8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQAB +tDlFdGhlcmV1bSBGb3VuZGF0aW9uIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QGV0 +aGVyZXVtLm9yZz6JAj4EEwECACgCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheA +BQJaCWH6BQkFo2BYAAoJEOiNMzT6X2oK+DEP/3H6dxkm0hvHZKoHLVuuxcu3EHYo +k5sd3MMWPrZSN8qzZnY7ayEDMxnarWOizc+2jfOxfJlzX/g8lR1/fsHdWPFPhPoV +Qk8ygrHn1H8U8+rpw/U03BqmqHpYCDzJ+CIis9UWROniqXw1nuqu/FtWOsdWxNKh +jUo6k/0EsaXsxRPzgJv7fEUcVcQ7as/C3x9sy3muc2gvgA4/BKoGPb1/U0GuA8lV +fDIDshAggmnSUAg+TuYSAAdoFQ1sKwFMPigcLJF2eyKuK3iUyixJrec/c4LSf3wA +cGghbeuqI8INP0Y2zvXDQN2cByxsFAuoZG+m0cyKGaDH2MVUvOKKYqn/03qvrf15 +AWAsW0l0yQwOTCo3FbsNzemClm5Bj/xH0E4XuwXwChcMCMOWJrFoxyvCEI+keoQc +c08/a8/MtS7vBAABXwOziSmm6CNqmzpWrh/fDrjlJlba9U3MxzvqU3IFlTdMratv +6V+SgX+L25lCzW4NxxUavoB8fAlvo8lxpHKo24FP+RcLQ8XqkU3RiUsgRjQRFOqQ +TaJcsp8mimmiYyf24mNu6b48pi+a5c/eQR9w59emeEUZqsJU+nqv8BWIIp7o4Agh +NYnKjkhPlY5e1fLVfAHIADZFynWwRPkPMJSrBiP5EtcOFxQGHGjRxU/KjXkvE0hV +xYb1PB8pWMTu/beeiQI+BBMBAgAoBQJYJd7YAhsDBQkB4TOABgsJCAcDAgYVCAIJ +CgsEFgIDAQIeAQIXgAAKCRDojTM0+l9qCplDD/9IZ2i+m1cnqQKtiyHbyFGx32oL +fzqPylX2bOG5DPsSTorSUdJMGVfT04oVxXc4S/2DVnNvi7RAbSiLapCWSplgtBOj +j1xlblOoXxT3m7s1XHGCX5tENxI9fVSSPVKJn+fQaWpPB2MhBA+1lUI6GJ+11T7K +J8LrP/fiw1/nOb7rW61HW44Gtyox23sA/d1+DsFVaF8hxJlNj5coPKr8xWzQ8pQl +juzdjHDukjevuw4rRmRq9vozvj9keEU9XJ5dldyEVXFmdDk7KT0p0Rla9nxYhzf/ +r/Bv8Bzy0HCWRb2D31BjXXGG05oVnYmNGxGFxYja4MwgrMmne3ilEVjfUJsapsqi +w41BAyQgIdfREulYN7ahsF5PrjVAqBd9IGtE8ULelF2SQxEBQBngEkP0ahP6tRAL +i7/CBjPKOyKijtqVny7qrGOnU2ygcA88/WDibexDhrjz0Gx8WmErU7rIWZiZ5u4Y +vJYVRo0+6rBCXRPeSJfiP5h1p17Anr2l42boAYslfcrzquB8MHtrNcyn650OLtHG +nbxgIdniKrpuzGN6Opw+O2id2JhD1/1p4SOemwAmthplr1MIyOHNP3q93rEj2J7h +5zPS/AJuKkMDFUpslPNLQjCOwPXtdzL7/kUZGBSyez1T3TaW1uY6l9XaJJRaSn+v +1zPgfp4GJ3lPs4AlAbQ0RXRoZXJldW0gRm91bmRhdGlvbiBCdWcgQm91bnR5IDxi +b3VudHlAZXRoZXJldW0ub3JnPokCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC +AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagoENg/+LnSaVeMxiGVtcjWl +b7Xd73yrEy4uxiESS1AalW9mMf7oZzfI05f7QIQlaLAkNac74vZDJbPKjtb7tpMO +RFhRZMCveq6CPKU6pd1SI8IUVUKwpEe6AJP3lHdVP57dquieFE2HlYKm6uHbCGWU +0cjyTA+uu2KbgCHGmofsPY/xOcZLGEHTHqa5w60JJAQm+BSDKnw8wTyrxGvA3EK/ +ePSvOZMYa+iw6vYuZeBIMbdiXR/A2keBi3GuvqB8tDMj7P22TrH5mVDm3zNqGYD6 +amDPeiWp4cztY3aZyLcgYotqXPpDceZzDn+HopBPzAb/llCdE7bVswKRhphVMw4b +bhL0R/TQY7Sf6TK2LKSBrjv0DWOSijikE71SJcBnJvHU7EpKrQQ0lMGclm3ynyji +Nf0YTPXQt4I+fwTmOew2GFeK3UytNWbWI7oXX7Nm4bj9bhf3IJ0kmZb/Gs73+xII +e7Rz52Mby436tWyQIQiF9ITYNGvNf53TwBBZMn0pKPiTyr3Ur7FHEotkEOFNh1// +4zQY10XxuBdLrYGyZ4V8xHJM+oKre8Eg2R9qHXVbjvErHE+7CvgnV7YUip0criPr +BlKRvuoJaSliH2JFhSjWVrkPmFGrWN0BAx10yIqMnEplfKeHf4P9Elek3oInS8WP +G1zJG6s/t5+hQK0X37+TB+6rd3GJAj4EEwECACgFAlgl4TsCGwMFCQHhM4AGCwkI +BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEOiNMzT6X2oKzf8P/iIKd77WHTbp4pMN +8h52HyZJtDJmjA1DPZrbGl1TesW/Z9uTd12txlgqZnbG2GfN9+LSP6EOPzR6v2xC +OVhR+RdWhZDJJuQCVS7lJIqQrZgmeTZG0TyQPZdLjVFBOrrhVwYX+HXbu429IzHr +URf5InyR1QgqOXyElDYS6e28HFqvaoA0DWTWDDqOLPVl+U5fuceIE2XXdv3AGLeP +Yf8J5MPobjPiZtBqI6S6iENY2Yn35qLX+axeC/iYSCHVtFuCCIdb/QYR1ZZV8Ps/ +aI9DwC7LU+YfPw7iqCIoqxSeA3o1PORkdSigEg3jtfRv5UqVo9a0oBb9jdoADsat +F/gW0E7mto3XGOiaR0eB9SSdsM3x7Bz4A0HIGNaxpZo1RWqlO91leP4c13Px7ISv +5OGXfLg+M8qb+qxbGd1HpitGi9s1y1aVfEj1kOtZ0tN8eu+Upg5WKwPNBDX3ar7J +9NCULgVSL+E79FG+zXw62gxiQrLfKzm4wU/9L5wVkwQnm29hLJ0tokrSBZFnc/1l +7OC+GM63tYicKkY4rqmoWUeYx7IwFH9mtDtvR1RxO85RbQhZizwpZpdpRkH0DqZu +ZJRmRa5r7rPqmfa7d+VIFhz2Xs8pJMLVqxTsLKcLglmjw7aOrYG0SWeH7YraXWGD +N3SlvSBiVwcK7QUKzLLvpadLwxfsuQINBFgl3tgBEACbgq6HTN5gEBi0lkD/MafI +nmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4hYontkMaKRlCg2Rvgjvk3Zve0 +PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT19BdeAQRFvcfd+8w8 +f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj26bf+2+1 +DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6 +D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66i +PsR99MQ7FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A +4tGkHl08KZ2N9o6GrfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8gr +eW8xB4zuf9Mkuou+RHNmo8PebHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0 +VRxdPImKun+4LOXbfOxArOSkY6i35+gsgkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9 +IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/bM1ACUtipMiIVeUs2uFiRjpz +A1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJaCWIIBQkFo2BYAAoJ +EOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg3IHMGxDM +b/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8 +KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0I +Q1UKKXvzZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0 +K9lneidcqtBDvlggJTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0T +NOOE8fXlvu8iuIAMBSDL9ep6sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd +5MTi0MDRNTij431kn8T/D0LCgmoUmYYMBgbwFhXr67axPZlKjrqR0z3F/Elv0ZPP +cVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1qScl9HiMxjt/H6aPastH63/7w +cN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4/Lih6Z1TlwcFVap+ +cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1pM6AOQPpZ +85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4 +=r6KK +-----END PGP PUBLIC KEY BLOCK----- +``` 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 08d5db979..7831a5ed3 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go @@ -21,6 +21,8 @@ import ( "encoding/json" "fmt" "io" + + "github.com/ethereum/go-ethereum/common" ) // The ABI holds information about a contract's context and available @@ -68,23 +70,43 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { return nil, err } // Pack up the method ID too if not a constructor and return - return append(method.Id(), 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 len(output) == 0 { +func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) { + if len(data) == 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 if method, ok := abi.Methods[name]; ok { - if len(output)%32 != 0 { - return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(output), output) + if len(data)%32 != 0 { + return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data) } - return method.Outputs.Unpack(v, output) - } else if event, ok := abi.Events[name]; ok { - return event.Inputs.Unpack(v, output) + return method.Outputs.Unpack(v, data) + } + if event, ok := abi.Events[name]; ok { + return event.Inputs.Unpack(v, data) + } + return fmt.Errorf("abi: could not locate named method or event") +} + +// UnpackIntoMap unpacks a log into the provided map[string]interface{} +func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) { + if len(data) == 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 + if method, ok := abi.Methods[name]; ok { + if len(data)%32 != 0 { + return fmt.Errorf("abi: improperly formatted output") + } + return method.Outputs.UnpackIntoMap(v, data) + } + if event, ok := abi.Events[name]; ok { + return event.Inputs.UnpackIntoMap(v, data) } return fmt.Errorf("abi: could not locate named method or event") } @@ -99,11 +121,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { Inputs []Argument Outputs []Argument } - if err := json.Unmarshal(data, &fields); err != nil { return err } - abi.Methods = make(map[string]Method) abi.Events = make(map[string]Event) for _, field := range fields { @@ -114,15 +134,29 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { } // empty defaults to function according to the abi spec case "function", "": - abi.Methods[field.Name] = Method{ - Name: field.Name, + name := field.Name + _, ok := abi.Methods[name] + for idx := 0; ok; idx++ { + name = fmt.Sprintf("%s%d", field.Name, idx) + _, ok = abi.Methods[name] + } + abi.Methods[name] = Method{ + Name: name, + RawName: field.Name, Const: field.Constant, Inputs: field.Inputs, Outputs: field.Outputs, } case "event": - abi.Events[field.Name] = Event{ - Name: field.Name, + name := field.Name + _, ok := abi.Events[name] + for idx := 0; ok; idx++ { + name = fmt.Sprintf("%s%d", field.Name, idx) + _, ok = abi.Events[name] + } + abi.Events[name] = Event{ + Name: name, + RawName: field.Name, Anonymous: field.Anonymous, Inputs: field.Inputs, } @@ -136,12 +170,23 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { // returns nil if none found func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { if len(sigdata) < 4 { - return nil, fmt.Errorf("data too short (% bytes) for abi method lookup", len(sigdata)) + return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata)) } for _, method := range abi.Methods { - if bytes.Equal(method.Id(), sigdata[:4]) { + if bytes.Equal(method.ID(), sigdata[:4]) { return &method, nil } } return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) } + +// EventByID looks an event up by its topic hash in the +// ABI and returns nil if none found. +func (abi *ABI) EventByID(topic common.Hash) (*Event, error) { + for _, event := range abi.Events { + if bytes.Equal(event.ID().Bytes(), topic.Bytes()) { + return &event, nil + } + } + return nil, fmt.Errorf("no event with id: %#x", topic.Hex()) +} 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 d0a6b035c..4dae58653 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go @@ -102,6 +102,16 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error { return arguments.unpackAtomic(v, marshalledValues[0]) } +// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value +func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { + marshalledValues, err := arguments.UnpackValues(data) + if err != nil { + return err + } + + return arguments.unpackIntoMap(v, marshalledValues) +} + // unpack sets the unmarshalled value to go format. // Note the dst here must be settable. func unpack(t *Type, dst interface{}, src interface{}) error { @@ -109,11 +119,22 @@ func unpack(t *Type, dst interface{}, src interface{}) error { dstVal = reflect.ValueOf(dst).Elem() srcVal = reflect.ValueOf(src) ) - - if t.T != TupleTy && !((t.T == SliceTy || t.T == ArrayTy) && t.Elem.T == TupleTy) { + tuple, typ := false, t + for { + if typ.T == SliceTy || typ.T == ArrayTy { + typ = typ.Elem + continue + } + tuple = typ.T == TupleTy + break + } + if !tuple { return set(dstVal, srcVal) } + // Dereferences interface or pointer wrapper + dstVal = indirectInterfaceOrPtr(dstVal) + switch t.T { case TupleTy: if dstVal.Kind() != reflect.Struct { @@ -160,6 +181,19 @@ func unpack(t *Type, dst interface{}, src interface{}) error { return nil } +// unpackIntoMap unpacks marshalledValues into the provided map[string]interface{} +func (arguments Arguments) unpackIntoMap(v map[string]interface{}, marshalledValues []interface{}) error { + // Make sure map is not nil + if v == nil { + return fmt.Errorf("abi: cannot unpack into a nil map") + } + + for i, arg := range arguments.NonIndexed() { + v[arg.Name] = marshalledValues[i] + } + return nil +} + // unpackAtomic unpacks ( hexdata -> go ) a single value func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { if arguments.LengthNonIndexed() == 0 { @@ -168,7 +202,7 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interfac argument := arguments.NonIndexed()[0] elem := reflect.ValueOf(v).Elem() - if elem.Kind() == reflect.Struct { + if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy { fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem) if err != nil { return err diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go index e6bb0c3b5..e51f0bd8e 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/auth.go @@ -22,6 +22,8 @@ import ( "io" "io/ioutil" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/external" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -42,6 +44,24 @@ func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) { return NewKeyedTransactor(key.PrivateKey), nil } +// NewKeyStoreTransactor is a utility method to easily create a transaction signer from +// an decrypted key from a keystore +func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) { + return &TransactOpts{ + From: account.Address, + Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) { + if address != account.Address { + return nil, errors.New("not authorized to sign this account") + } + signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes()) + if err != nil { + return nil, err + } + return tx.WithSignature(signer, signature) + }, + }, nil +} + // NewKeyedTransactor is a utility method to easily create a transaction signer // from a single private key. func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts { @@ -60,3 +80,17 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts { }, } } + +// NewClefTransactor is a utility method to easily create a transaction signer +// with a clef backend. +func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts { + return &TransactOpts{ + From: account.Address, + Signer: func(signer types.Signer, address common.Address, transaction *types.Transaction) (*types.Transaction, error) { + if address != account.Address { + return nil, errors.New("not authorized to sign this account") + } + return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id + }, + } +} 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 3cb9352c1..e30572e0a 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 @@ -45,8 +45,10 @@ import ( // This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend. var _ bind.ContractBackend = (*SimulatedBackend)(nil) -var errBlockNumberUnsupported = errors.New("SimulatedBackend cannot access blocks other than the latest block") -var errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction") +var ( + errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block") + errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction") +) // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in // the background. Its main purpose is to allow easily testing contract bindings. @@ -63,10 +65,9 @@ type SimulatedBackend struct { config *params.ChainConfig } -// NewSimulatedBackend creates a new binding backend using a simulated blockchain -// for testing purposes. -func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { - database := ethdb.NewMemDatabase() +// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database +// and uses a simulated blockchain for testing purposes. +func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} genesis.MustCommit(database) blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil) @@ -81,6 +82,18 @@ func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBac return backend } +// NewSimulatedBackend creates a new binding backend using a simulated blockchain +// for testing purposes. +func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { + return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit) +} + +// Close terminates the underlying blockchain's update loop. +func (b *SimulatedBackend) Close() error { + b.blockchain.Stop() + return nil +} + // Commit imports all the pending transactions as a single block and starts a // fresh new state. func (b *SimulatedBackend) Commit() { @@ -160,10 +173,29 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres // TransactionReceipt returns the receipt of a transaction. func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash) + receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config) return receipt, nil } +// TransactionByHash checks the pool of pending transactions in addition to the +// blockchain. The isPending return value indicates whether the transaction has been +// mined yet. Note that the transaction may not be part of the canonical chain even if +// it's not pending. +func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { + b.mu.Lock() + defer b.mu.Unlock() + + tx := b.pendingBlock.Transaction(txHash) + if tx != nil { + return tx, true, nil + } + tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash) + if tx != nil { + return tx, false, nil + } + return nil, false, ethereum.NotFound +} + // PendingCodeAt returns the code associated with an account in the pending state. func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { b.mu.Lock() @@ -296,7 +328,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { b.mu.Lock() defer b.mu.Unlock() - sender, err := types.Sender(types.NewEIP155Signer(tx.ChainId()), tx) + + sender, err := types.Sender(types.NewEIP155Signer(b.config.ChainID), tx) if err != nil { panic(fmt.Errorf("invalid transaction: %v", err)) } @@ -404,6 +437,11 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { return nil } +// Blockchain returns the underlying blockchain. +func (b *SimulatedBackend) Blockchain() *core.BlockChain { + return b.blockchain +} + // callmsg implements core.Message to allow passing it as a transaction simulator. type callmsg struct { ethereum.CallMsg @@ -444,7 +482,7 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ if number == nil { return nil, nil } - return rawdb.ReadReceipts(fb.db, hash, *number), nil + return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil } func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { @@ -452,7 +490,7 @@ func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*ty if number == nil { return nil, nil } - receipts := rawdb.ReadReceipts(fb.db, hash, *number) + receipts := rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()) if receipts == nil { return nil, nil } 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 c37bdf11d..f74a0af21 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 @@ -252,7 +252,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int 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...) + query = append([][]interface{}{{c.abi.Events[name].ID()}}, query...) topics, err := makeTopics(query...) if err != nil { @@ -301,7 +301,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter 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...) + query = append([][]interface{}{{c.abi.Events[name].ID()}}, query...) topics, err := makeTopics(query...) if err != nil { @@ -340,6 +340,22 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) return parseTopics(out, indexed, log.Topics[1:]) } +// UnpackLogIntoMap unpacks a retrieved log into the provided map. +func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error { + if len(log.Data) > 0 { + if err := c.abi.UnpackIntoMap(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 parseTopicsIntoMap(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 { 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 5ee30d024..dc51e2a7e 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 @@ -22,6 +22,7 @@ package bind import ( "bytes" + "errors" "fmt" "go/format" "regexp" @@ -30,6 +31,7 @@ import ( "unicode" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/log" ) // Lang is a target programming language selector to generate bindings for. @@ -45,10 +47,13 @@ const ( // to be used as is in client code, but rather as an intermediate struct which // enforces compile time type safety and naming convention opposed to having to // manually maintain hard coded strings that break on runtime. -func Bind(types []string, abis []string, bytecodes []string, pkg string, lang Lang) (string, error) { +func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string) (string, error) { // Process each individual contract requested binding contracts := make(map[string]*tmplContract) + // Map used to flag each encountered library as such + isLib := make(map[string]struct{}) + for i := 0; i < len(types); i++ { // Parse the actual ABI to generate the binding for evmABI, err := abi.JSON(strings.NewReader(abis[i])) @@ -63,11 +68,12 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La return r }, abis[i]) - // Extract the call and transact methods; events; and sort them alphabetically + // Extract the call and transact methods; events, struct definitions; and sort them alphabetically var ( calls = make(map[string]*tmplMethod) transacts = make(map[string]*tmplMethod) events = make(map[string]*tmplEvent) + structs = make(map[string]*tmplStruct) ) for _, original := range evmABI.Methods { // Normalize the method for capital cases and non-anonymous inputs/outputs @@ -80,6 +86,9 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La if input.Name == "" { normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) } + if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist { + bindStructType[lang](input.Type, structs) + } } normalized.Outputs = make([]abi.Argument, len(original.Outputs)) copy(normalized.Outputs, original.Outputs) @@ -87,6 +96,9 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La if output.Name != "" { normalized.Outputs[j].Name = capitalise(output.Name) } + if _, exist := structs[output.Type.String()]; output.Type.T == abi.TupleTy && !exist { + bindStructType[lang](output.Type, structs) + } } // Append the methods to the call or transact lists if original.Const { @@ -112,25 +124,61 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La if input.Name == "" { normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) } + if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist { + bindStructType[lang](input.Type, structs) + } } } // Append the event to the accumulator list events[original.Name] = &tmplEvent{Original: original, Normalized: normalized} } + + // There is no easy way to pass arbitrary java objects to the Go side. + if len(structs) > 0 && lang == LangJava { + return "", errors.New("java binding for tuple arguments is not supported yet") + } + contracts[types[i]] = &tmplContract{ Type: capitalise(types[i]), InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1), - InputBin: strings.TrimSpace(bytecodes[i]), + InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"), Constructor: evmABI.Constructor, Calls: calls, Transacts: transacts, Events: events, + Libraries: make(map[string]string), + Structs: structs, } + // Function 4-byte signatures are stored in the same sequence + // as types, if available. + if len(fsigs) > i { + contracts[types[i]].FuncSigs = fsigs[i] + } + // Parse library references. + for pattern, name := range libs { + matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin)) + if err != nil { + log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err) + } + if matched { + contracts[types[i]].Libraries[pattern] = name + // keep track that this type is a library + if _, ok := isLib[name]; !ok { + isLib[name] = struct{}{} + } + } + } + } + // Check if that type has already been identified as a library + for i := 0; i < len(types); i++ { + _, ok := isLib[types[i]] + contracts[types[i]].Library = ok } // Generate the contract template data content and render it data := &tmplData{ Package: pkg, Contracts: contracts, + Libraries: libs, } buffer := new(bytes.Buffer) @@ -138,6 +186,8 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La "bindtype": bindType[lang], "bindtopictype": bindTopicType[lang], "namedtype": namedType[lang], + "formatmethod": formatMethod, + "formatevent": formatEvent, "capitalise": capitalise, "decapitalise": decapitalise, } @@ -159,129 +209,67 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La // bindType is a set of type binders that convert Solidity types to some supported // programming language types. -var bindType = map[Lang]func(kind abi.Type) string{ +var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ LangGo: bindTypeGo, LangJava: bindTypeJava, } -// Helper function for the binding generators. -// It reads the unmatched characters after the inner type-match, -// (since the inner type is a prefix of the total type declaration), -// looks for valid arrays (possibly a dynamic one) wrapping the inner type, -// and returns the sizes of these arrays. -// -// Returned array sizes are in the same order as solidity signatures; inner array size first. -// Array sizes may also be "", indicating a dynamic array. -func wrapArray(stringKind string, innerLen int, innerMapping string) (string, []string) { - remainder := stringKind[innerLen:] - //find all the sizes - matches := regexp.MustCompile(`\[(\d*)\]`).FindAllStringSubmatch(remainder, -1) - parts := make([]string, 0, len(matches)) - for _, match := range matches { - //get group 1 from the regex match - parts = append(parts, match[1]) - } - return innerMapping, parts -} - -// Translates the array sizes to a Go-lang declaration of a (nested) array of the inner type. -// Simply returns the inner type if arraySizes is empty. -func arrayBindingGo(inner string, arraySizes []string) string { - out := "" - //prepend all array sizes, from outer (end arraySizes) to inner (start arraySizes) - for i := len(arraySizes) - 1; i >= 0; i-- { - out += "[" + arraySizes[i] + "]" - } - out += inner - return out -} - -// bindTypeGo converts a Solidity type to a Go one. Since there is no clear mapping -// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly -// mapped will use an upscaled type (e.g. *big.Int). -func bindTypeGo(kind abi.Type) string { - stringKind := kind.String() - innerLen, innerMapping := bindUnnestedTypeGo(stringKind) - return arrayBindingGo(wrapArray(stringKind, innerLen, innerMapping)) -} - -// The inner function of bindTypeGo, this finds the inner type of stringKind. -// (Or just the type itself if it is not an array or slice) -// The length of the matched part is returned, with the translated type. -func bindUnnestedTypeGo(stringKind string) (int, string) { - - switch { - case strings.HasPrefix(stringKind, "address"): - return len("address"), "common.Address" - - case strings.HasPrefix(stringKind, "bytes"): - parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind) - return len(parts[0]), fmt.Sprintf("[%s]byte", parts[1]) - - case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"): - parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind) +// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go one. +func bindBasicTypeGo(kind abi.Type) string { + switch kind.T { + case abi.AddressTy: + return "common.Address" + case abi.IntTy, abi.UintTy: + parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String()) switch parts[2] { case "8", "16", "32", "64": - return len(parts[0]), fmt.Sprintf("%sint%s", parts[1], parts[2]) + return fmt.Sprintf("%sint%s", parts[1], parts[2]) } - return len(parts[0]), "*big.Int" - - case strings.HasPrefix(stringKind, "bool"): - return len("bool"), "bool" - - case strings.HasPrefix(stringKind, "string"): - return len("string"), "string" - + return "*big.Int" + case abi.FixedBytesTy: + return fmt.Sprintf("[%d]byte", kind.Size) + case abi.BytesTy: + return "[]byte" + case abi.FunctionTy: + return "[24]byte" default: - return len(stringKind), stringKind + // string, bool types + return kind.String() } } -// Translates the array sizes to a Java declaration of a (nested) array of the inner type. -// Simply returns the inner type if arraySizes is empty. -func arrayBindingJava(inner string, arraySizes []string) string { - // Java array type declarations do not include the length. - return inner + strings.Repeat("[]", len(arraySizes)) -} - -// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping -// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly +// bindTypeGo converts solidity types to Go ones. Since there is no clear mapping +// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly // mapped will use an upscaled type (e.g. BigDecimal). -func bindTypeJava(kind abi.Type) string { - stringKind := kind.String() - innerLen, innerMapping := bindUnnestedTypeJava(stringKind) - return arrayBindingJava(wrapArray(stringKind, innerLen, innerMapping)) +func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { + switch kind.T { + case abi.TupleTy: + return structs[kind.String()].Name + case abi.ArrayTy: + return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem, structs) + case abi.SliceTy: + return "[]" + bindTypeGo(*kind.Elem, structs) + default: + return bindBasicTypeGo(kind) + } } -// The inner function of bindTypeJava, this finds the inner type of stringKind. -// (Or just the type itself if it is not an array or slice) -// The length of the matched part is returned, with the translated type. -func bindUnnestedTypeJava(stringKind string) (int, string) { - - switch { - case strings.HasPrefix(stringKind, "address"): - parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind) - if len(parts) != 2 { - return len(stringKind), stringKind - } - if parts[1] == "" { - return len("address"), "Address" - } - return len(parts[0]), "Addresses" - - case strings.HasPrefix(stringKind, "bytes"): - parts := regexp.MustCompile(`bytes([0-9]*)`).FindStringSubmatch(stringKind) - if len(parts) != 2 { - return len(stringKind), stringKind - } - return len(parts[0]), "byte[]" - - case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"): - //Note that uint and int (without digits) are also matched, +// bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java one. +func bindBasicTypeJava(kind abi.Type) string { + switch kind.T { + case abi.AddressTy: + return "Address" + case abi.IntTy, abi.UintTy: + // Note that uint and int (without digits) are also matched, // these are size 256, and will translate to BigInt (the default). - parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(stringKind) + parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String()) if len(parts) != 3 { - return len(stringKind), stringKind + return kind.String() + } + // All unsigned integers should be translated to BigInt since gomobile doesn't + // support them. + if parts[1] == "u" { + return "BigInt" } namedSize := map[string]string{ @@ -291,50 +279,146 @@ func bindUnnestedTypeJava(stringKind string) (int, string) { "64": "long", }[parts[2]] - //default to BigInt + // default to BigInt if namedSize == "" { namedSize = "BigInt" } - return len(parts[0]), namedSize - - case strings.HasPrefix(stringKind, "bool"): - return len("bool"), "boolean" - - case strings.HasPrefix(stringKind, "string"): - return len("string"), "String" - + return namedSize + case abi.FixedBytesTy, abi.BytesTy: + return "byte[]" + case abi.BoolTy: + return "boolean" + case abi.StringTy: + return "String" + case abi.FunctionTy: + return "byte[24]" default: - return len(stringKind), stringKind + return kind.String() + } +} + +// pluralizeJavaType explicitly converts multidimensional types to predefined +// type in go side. +func pluralizeJavaType(typ string) string { + switch typ { + case "boolean": + return "Bools" + case "String": + return "Strings" + case "Address": + return "Addresses" + case "byte[]": + return "Binaries" + case "BigInt": + return "BigInts" + } + return typ + "[]" +} + +// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping +// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly +// mapped will use an upscaled type (e.g. BigDecimal). +func bindTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { + switch kind.T { + case abi.TupleTy: + return structs[kind.String()].Name + case abi.ArrayTy, abi.SliceTy: + return pluralizeJavaType(bindTypeJava(*kind.Elem, structs)) + default: + return bindBasicTypeJava(kind) } } // 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{ +var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ LangGo: bindTopicTypeGo, LangJava: bindTopicTypeJava, } -// bindTypeGo converts a Solidity topic type to a Go one. It is almost the same +// bindTopicTypeGo 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) +func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { + bound := bindTypeGo(kind, structs) 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 +// bindTopicTypeJava 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" { +func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { + bound := bindTypeJava(kind, structs) + if bound == "String" || bound == "byte[]" { bound = "Hash" } return bound } +// bindStructType is a set of type binders that convert Solidity tuple types to some supported +// programming language struct definition. +var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ + LangGo: bindStructTypeGo, + LangJava: bindStructTypeJava, +} + +// bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping +// in the given map. +// Notably, this function will resolve and record nested struct recursively. +func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { + switch kind.T { + case abi.TupleTy: + if s, exist := structs[kind.String()]; exist { + return s.Name + } + var fields []*tmplField + for i, elem := range kind.TupleElems { + field := bindStructTypeGo(*elem, structs) + fields = append(fields, &tmplField{Type: field, Name: capitalise(kind.TupleRawNames[i]), SolKind: *elem}) + } + name := fmt.Sprintf("Struct%d", len(structs)) + structs[kind.String()] = &tmplStruct{ + Name: name, + Fields: fields, + } + return name + case abi.ArrayTy: + return fmt.Sprintf("[%d]", kind.Size) + bindStructTypeGo(*kind.Elem, structs) + case abi.SliceTy: + return "[]" + bindStructTypeGo(*kind.Elem, structs) + default: + return bindBasicTypeGo(kind) + } +} + +// bindStructTypeJava converts a Solidity tuple type to a Java one and records the mapping +// in the given map. +// Notably, this function will resolve and record nested struct recursively. +func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { + switch kind.T { + case abi.TupleTy: + if s, exist := structs[kind.String()]; exist { + return s.Name + } + var fields []*tmplField + for i, elem := range kind.TupleElems { + field := bindStructTypeJava(*elem, structs) + fields = append(fields, &tmplField{Type: field, Name: decapitalise(kind.TupleRawNames[i]), SolKind: *elem}) + } + name := fmt.Sprintf("Class%d", len(structs)) + structs[kind.String()] = &tmplStruct{ + Name: name, + Fields: fields, + } + return name + case abi.ArrayTy, abi.SliceTy: + return pluralizeJavaType(bindStructTypeJava(*kind.Elem, structs)) + default: + return bindBasicTypeJava(kind) + } +} + // 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{ @@ -348,18 +432,8 @@ func namedTypeJava(javaKind string, solKind abi.Type) string { switch javaKind { case "byte[]": return "Binary" - case "byte[][]": - return "Binaries" - case "string": - return "String" - case "string[]": - return "Strings" case "boolean": return "Bool" - case "boolean[]": - return "Bools" - case "BigInt[]": - return "BigInts" default: parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String()) if len(parts) != 4 { @@ -422,3 +496,63 @@ func structured(args abi.Arguments) bool { } return true } + +// resolveArgName converts a raw argument representation into a user friendly format. +func resolveArgName(arg abi.Argument, structs map[string]*tmplStruct) string { + var ( + prefix string + embedded string + typ = &arg.Type + ) +loop: + for { + switch typ.T { + case abi.SliceTy: + prefix += "[]" + case abi.ArrayTy: + prefix += fmt.Sprintf("[%d]", typ.Size) + default: + embedded = typ.String() + break loop + } + typ = typ.Elem + } + if s, exist := structs[embedded]; exist { + return prefix + s.Name + } else { + return arg.Type.String() + } +} + +// formatMethod transforms raw method representation into a user friendly one. +func formatMethod(method abi.Method, structs map[string]*tmplStruct) string { + inputs := make([]string, len(method.Inputs)) + for i, input := range method.Inputs { + inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name) + } + outputs := make([]string, len(method.Outputs)) + for i, output := range method.Outputs { + outputs[i] = resolveArgName(output, structs) + if len(output.Name) > 0 { + outputs[i] += fmt.Sprintf(" %v", output.Name) + } + } + constant := "" + if method.Const { + constant = "constant " + } + return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", ")) +} + +// formatEvent transforms raw event representation into a user friendly one. +func formatEvent(event abi.Event, structs map[string]*tmplStruct) string { + inputs := make([]string, len(event.Inputs)) + for i, input := range event.Inputs { + if input.Indexed { + inputs[i] = fmt.Sprintf("%v indexed %v", resolveArgName(input, structs), input.Name) + } else { + inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name) + } + } + return fmt.Sprintf("event %v(%v)", event.RawName, strings.Join(inputs, ", ")) +} 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 02d0258e0..4ec65474b 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 @@ -22,6 +22,7 @@ import "github.com/ethereum/go-ethereum/accounts/abi" type tmplData struct { Package string // Name of the package to place the generated file in Contracts map[string]*tmplContract // List of contracts to generate into this file + Libraries map[string]string // Map the bytecode's link pattern to the library name } // tmplContract contains the data needed to generate an individual contract binding. @@ -29,10 +30,14 @@ type tmplContract struct { Type string // Type name of the main contract binding InputABI string // JSON ABI used as the input to generate the binding from InputBin string // Optional EVM bytecode used to denetare deploy code from + FuncSigs map[string]string // Optional map: string signature -> 4-byte signature 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 + Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs + Structs map[string]*tmplStruct // Contract struct type definitions + Library bool } // tmplMethod is a wrapper around an abi.Method that contains a few preprocessed @@ -49,6 +54,21 @@ type tmplEvent struct { Normalized abi.Event // Normalized version of the parsed fields } +// tmplField is a wrapper around a struct field with binding language +// struct type definition and relative filed name. +type tmplField struct { + Type string // Field type representation depends on target binding language + Name string // Field name converted from the raw user-defined field name + SolKind abi.Type // Raw abi type information +} + +// tmplStruct is a wrapper around an abi.tuple contains a auto-generated +// struct name. +type tmplStruct struct { + Name string // Auto-generated struct name(We can't obtain the raw struct name through abi) + Fields []*tmplField // Struct fields definition depends on the binding language. +} + // tmplSource is language to template mapping containing all the supported // programming languages the package can generate to. var tmplSource = map[Lang]string{ @@ -89,19 +109,32 @@ var ( ) {{range $contract := .Contracts}} + {{$structs := $contract.Structs}} // {{.Type}}ABI is the input ABI used to generate the binding from. const {{.Type}}ABI = "{{.InputABI}}" + {{if $contract.FuncSigs}} + // {{.Type}}FuncSigs maps the 4-byte function signature to its string representation. + var {{.Type}}FuncSigs = map[string]string{ + {{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}", + {{end}} + } + {{end}} + {{if .InputBin}} // {{.Type}}Bin is the compiled bytecode used for deploying new contracts. - const {{.Type}}Bin = ` + "`" + `{{.InputBin}}` + "`" + ` + var {{.Type}}Bin = "0x{{.InputBin}}" // Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it. - func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) { + func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) { parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI)) if err != nil { return common.Address{}, nil, nil, err } + {{range $pattern, $name := .Libraries}} + {{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend) + {{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1) + {{end}} address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}}) if err != nil { return common.Address{}, nil, nil, err @@ -114,7 +147,7 @@ var ( 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}}Filterer // Log filterer for contract events } // {{.Type}}Caller is an auto generated read-only Go binding around an Ethereum contract. @@ -252,16 +285,24 @@ var ( return _{{$contract.Type}}.Contract.contract.Transact(opts, method, params...) } + {{range .Structs}} + // {{.Name}} is an auto generated low-level Go binding around an user-defined struct. + type {{.Name}} struct { + {{range $field := .Fields}} + {{$field.Name}} {{$field.Type}}{{end}} + } + {{end}} + {{range .Calls}} - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type}},{{end}}{{end}} error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) { {{if .Structured}}ret := new(struct{ - {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type}} + {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}} {{end}} }){{else}}var ( - {{range $i, $_ := .Normalized.Outputs}}ret{{$i}} = new({{bindtype .Type}}) + {{range $i, $_ := .Normalized.Outputs}}ret{{$i}} = new({{bindtype .Type $structs}}) {{end}} ){{end}} out := {{if .Structured}}ret{{else}}{{if eq (len .Normalized.Outputs) 1}}ret0{{else}}&[]interface{}{ @@ -272,40 +313,40 @@ var ( return {{if .Structured}}*ret,{{else}}{{range $i, $_ := .Normalized.Outputs}}*ret{{$i}},{{end}}{{end}} err } - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type}},{{end}} {{end}} error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) { return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}}) } - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type}},{{end}} {{end}} error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) { return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}}) } {{end}} {{range .Transacts}} - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type}} {{end}}) (*types.Transaction, error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}}) } - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type}} {{end}}) (*types.Transaction, error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}}) } - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.Id}}. + // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type}} {{end}}) (*types.Transaction, error) { + // Solidity: {{formatmethod .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}}) } {{end}} @@ -377,14 +418,14 @@ var ( // {{$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}} + {{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{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}}. + // 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) { + // Solidity: {{formatevent .Original $structs}} + func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) { {{range .Normalized.Inputs}} {{if .Indexed}}var {{.Name}}Rule []interface{} for _, {{.Name}}Item := range {{.Name}} { @@ -398,10 +439,10 @@ var ( 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}}. + // 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) { + // Solidity: {{formatevent .Original $structs}} + 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 $structs}}{{end}}{{end}}) (event.Subscription, error) { {{range .Normalized.Inputs}} {{if .Indexed}}var {{.Name}}Rule []interface{} for _, {{.Name}}Item := range {{.Name}} { @@ -439,6 +480,18 @@ var ( } }), nil } + + // Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}. + // + // Solidity: {{.Original.String}} + func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) { + event := new({{$contract.Type}}{{.Normalized.Name}}) + if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil { + return nil, err + } + return event, nil + } + {{end}} {{end}} ` @@ -452,95 +505,112 @@ const tmplSourceJava = ` package {{.Package}}; import org.ethereum.geth.*; -import org.ethereum.geth.internal.*; +import java.util.*; {{range $contract := .Contracts}} - public class {{.Type}} { - // ABI is the input ABI used to generate the binding from. - public final static String ABI = "{{.InputABI}}"; - - {{if .InputBin}} - // BYTECODE is the compiled bytecode used for deploying new contracts. - public final static byte[] BYTECODE = "{{.InputBin}}".getBytes(); - - // deploy deploys a new Ethereum contract, binding an instance of {{.Type}} to it. - public static {{.Type}} deploy(TransactOpts auth, EthereumClient client{{range .Constructor.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception { - Interfaces args = Geth.newInterfaces({{(len .Constructor.Inputs)}}); - {{range $index, $element := .Constructor.Inputs}} - args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}}); - {{end}} - return new {{.Type}}(Geth.deployContract(auth, ABI, BYTECODE, client, args)); - } - - // Internal constructor used by contract deployment. - private {{.Type}}(BoundContract deployment) { - this.Address = deployment.getAddress(); - this.Deployer = deployment.getDeployer(); - this.Contract = deployment; - } - {{end}} - - // Ethereum address where this contract is located at. - public final Address Address; - - // Ethereum transaction in which this contract was deployed (if known!). - public final Transaction Deployer; - - // Contract instance bound to a blockchain address. - private final BoundContract Contract; - - // Creates a new instance of {{.Type}}, bound to a specific deployed contract. - public {{.Type}}(Address address, EthereumClient client) throws Exception { - this(Geth.bindContract(address, ABI, client)); - } - - {{range .Calls}} - {{if gt (len .Normalized.Outputs) 1}} - // {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}. - public class {{capitalise .Normalized.Name}}Results { - {{range $index, $item := .Normalized.Outputs}}public {{bindtype .Type}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}}; - {{end}} - } +{{$structs := $contract.Structs}} +{{if not .Library}}public {{end}}class {{.Type}} { + // ABI is the input ABI used to generate the binding from. + public final static String ABI = "{{.InputABI}}"; + {{if $contract.FuncSigs}} + // {{.Type}}FuncSigs maps the 4-byte function signature to its string representation. + public final static Map {{.Type}}FuncSigs; + static { + Hashtable temp = new Hashtable(); + {{range $strsig, $binsig := .FuncSigs}}temp.put("{{$binsig}}", "{{$strsig}}"); {{end}} + {{.Type}}FuncSigs = Collections.unmodifiableMap(temp); + } + {{end}} + {{if .InputBin}} + // BYTECODE is the compiled bytecode used for deploying new contracts. + public final static String BYTECODE = "0x{{.InputBin}}"; - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.Id}}. - // - // Solidity: {{.Original.String}} - public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else}}{{range .Normalized.Outputs}}{{bindtype .Type}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception { - Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}}); - {{range $index, $item := .Normalized.Inputs}}args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}}); - {{end}} + // deploy deploys a new Ethereum contract, binding an instance of {{.Type}} to it. + public static {{.Type}} deploy(TransactOpts auth, EthereumClient client{{range .Constructor.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception { + Interfaces args = Geth.newInterfaces({{(len .Constructor.Inputs)}}); + String bytecode = BYTECODE; + {{if .Libraries}} - Interfaces results = Geth.newInterfaces({{(len .Normalized.Outputs)}}); - {{range $index, $item := .Normalized.Outputs}}Interface result{{$index}} = Geth.newInterface(); result{{$index}}.setDefault{{namedtype (bindtype .Type) .Type}}(); results.set({{$index}}, result{{$index}}); - {{end}} - - if (opts == null) { - opts = Geth.newCallOpts(); - } - this.Contract.call(opts, results, "{{.Original.Name}}", args); - {{if gt (len .Normalized.Outputs) 1}} - {{capitalise .Normalized.Name}}Results result = new {{capitalise .Normalized.Name}}Results(); - {{range $index, $item := .Normalized.Outputs}}result.{{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}} = results.get({{$index}}).get{{namedtype (bindtype .Type) .Type}}(); - {{end}} - return result; - {{else}}{{range .Normalized.Outputs}}return results.get(0).get{{namedtype (bindtype .Type) .Type}}();{{end}} - {{end}} - } + // "link" contract to dependent libraries by deploying them first. + {{range $pattern, $name := .Libraries}} + {{capitalise $name}} {{decapitalise $name}}Inst = {{capitalise $name}}.deploy(auth, client); + bytecode = bytecode.replace("__${{$pattern}}$__", {{decapitalise $name}}Inst.Address.getHex().substring(2)); {{end}} + {{end}} + {{range $index, $element := .Constructor.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}}); + {{end}} + return new {{.Type}}(Geth.deployContract(auth, ABI, Geth.decodeFromHex(bytecode), client, args)); + } - {{range .Transacts}} - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.Id}}. - // - // Solidity: {{.Original.String}} - public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception { - Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}}); - {{range $index, $item := .Normalized.Inputs}}args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}}); - {{end}} + // Internal constructor used by contract deployment. + private {{.Type}}(BoundContract deployment) { + this.Address = deployment.getAddress(); + this.Deployer = deployment.getDeployer(); + this.Contract = deployment; + } + {{end}} - return this.Contract.transact(opts, "{{.Original.Name}}" , args); - } + // Ethereum address where this contract is located at. + public final Address Address; + + // Ethereum transaction in which this contract was deployed (if known!). + public final Transaction Deployer; + + // Contract instance bound to a blockchain address. + private final BoundContract Contract; + + // Creates a new instance of {{.Type}}, bound to a specific deployed contract. + public {{.Type}}(Address address, EthereumClient client) throws Exception { + this(Geth.bindContract(address, ABI, client)); + } + + {{range .Calls}} + {{if gt (len .Normalized.Outputs) 1}} + // {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}. + public class {{capitalise .Normalized.Name}}Results { + {{range $index, $item := .Normalized.Outputs}}public {{bindtype .Type $structs}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}}; {{end}} } + {{end}} + + // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. + // + // Solidity: {{.Original.String}} + public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception { + Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}}); + {{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}}); + {{end}} + + Interfaces results = Geth.newInterfaces({{(len .Normalized.Outputs)}}); + {{range $index, $item := .Normalized.Outputs}}Interface result{{$index}} = Geth.newInterface(); result{{$index}}.setDefault{{namedtype (bindtype .Type $structs) .Type}}(); results.set({{$index}}, result{{$index}}); + {{end}} + + if (opts == null) { + opts = Geth.newCallOpts(); + } + this.Contract.call(opts, results, "{{.Original.Name}}", args); + {{if gt (len .Normalized.Outputs) 1}} + {{capitalise .Normalized.Name}}Results result = new {{capitalise .Normalized.Name}}Results(); + {{range $index, $item := .Normalized.Outputs}}result.{{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}} = results.get({{$index}}).get{{namedtype (bindtype .Type $structs) .Type}}(); + {{end}} + return result; + {{else}}{{range .Normalized.Outputs}}return results.get(0).get{{namedtype (bindtype .Type $structs) .Type}}();{{end}} + {{end}} + } + {{end}} + + {{range .Transacts}} + // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. + // + // Solidity: {{.Original.String}} + public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception { + Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}}); + {{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}}); + {{end}} + return this.Contract.transact(opts, "{{.Original.Name}}" , args); + } + {{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 index 600dfcda9..c7657b4a4 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go @@ -17,6 +17,7 @@ package bind import ( + "encoding/binary" "errors" "fmt" "math/big" @@ -83,8 +84,10 @@ func makeTopics(query ...[]interface{}) ([][]common.Hash, error) { val := reflect.ValueOf(rule) switch { + + // static byte array case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: - reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val) + reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val) default: return nil, fmt.Errorf("unsupported indexed type: %T", rule) @@ -175,8 +178,10 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er default: // Ran out of custom types, try the crazies switch { + + // static byte array case arg.Type.T == abi.FixedBytesTy: - reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:])) + reflect.Copy(field, reflect.ValueOf(topics[0][:arg.Type.Size])) default: return fmt.Errorf("unsupported indexed type: %v", arg.Type) @@ -187,3 +192,50 @@ func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) er } return nil } + +// parseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs +func parseTopicsIntoMap(out map[string]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") + } + + switch arg.Type.T { + case abi.BoolTy: + out[arg.Name] = topics[0][common.HashLength-1] == 1 + case abi.IntTy, abi.UintTy: + num := new(big.Int).SetBytes(topics[0][:]) + out[arg.Name] = num + case abi.AddressTy: + var addr common.Address + copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) + out[arg.Name] = addr + case abi.HashTy: + out[arg.Name] = topics[0] + case abi.FixedBytesTy: + out[arg.Name] = topics[0][:] + case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: + // Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash + // whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash + out[arg.Name] = topics[0] + case abi.FunctionTy: + if garbage := binary.BigEndian.Uint64(topics[0][0:8]); garbage != 0 { + return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[0].Bytes()) + } + var tmp [24]byte + copy(tmp[:], topics[0][8:32]) + out[arg.Name] = tmp + default: // Not handling tuples + 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 9392c1990..f1474813a 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go @@ -28,7 +28,18 @@ import ( // holds type information (inputs) about the yielded output. Anonymous events // don't get the signature canonical representation as the first LOG topic. type Event struct { - Name string + // Name is the event name used for internal representation. It's derived from + // the raw name and a suffix will be added in the case of a event overload. + // + // e.g. + // There are two events have same name: + // * foo(int,int) + // * foo(uint,uint) + // The event name of the first one wll be resolved as foo while the second one + // will be resolved as foo0. + Name string + // RawName is the raw event name parsed from ABI. + RawName string Anonymous bool Inputs Arguments } @@ -41,17 +52,26 @@ func (e Event) String() string { inputs[i] = fmt.Sprintf("%v indexed %v", input.Type, input.Name) } } - return fmt.Sprintf("event %v(%v)", e.Name, strings.Join(inputs, ", ")) + return fmt.Sprintf("event %v(%v)", e.RawName, strings.Join(inputs, ", ")) } -// Id returns the canonical representation of the event's signature used by the -// abi definition to identify event names and types. -func (e Event) Id() common.Hash { +// Sig returns the event string signature according to the ABI spec. +// +// Example +// +// event foo(uint32 a, int b) = "foo(uint32,int256)" +// +// Please note that "int" is substitute for its canonical representation "int256" +func (e Event) Sig() string { types := make([]string, len(e.Inputs)) - i := 0 - for _, input := range e.Inputs { + for i, input := range e.Inputs { types[i] = input.Type.String() - i++ } - return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ","))))) + return fmt.Sprintf("%v(%v)", e.RawName, strings.Join(types, ",")) +} + +// ID returns the canonical representation of the event's signature used by the +// abi definition to identify event names and types. +func (e Event) ID() common.Hash { + return common.BytesToHash(crypto.Keccak256([]byte(e.Sig()))) } 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 2d8d3d658..7da2e18fc 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go @@ -27,12 +27,23 @@ import ( // 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 -// from the storage and therefor requires no Tx to be send to the +// from the storage and therefore requires no Tx to be send to the // network. A method such as `Transact` does require a Tx and thus will -// be flagged `true`. +// be flagged `false`. // Input specifies the required input parameters for this gives method. type Method struct { - Name string + // Name is the method name used for internal representation. It's derived from + // the raw name and a suffix will be added in the case of a function overload. + // + // e.g. + // There are two functions have same name: + // * foo(int,int) + // * foo(uint,uint) + // The method name of the first one will be resolved as foo while the second one + // will be resolved as foo0. + Name string + // RawName is the raw method name parsed from ABI. + RawName string Const bool Inputs Arguments Outputs Arguments @@ -42,7 +53,7 @@ type Method struct { // // Example // -// function foo(uint32 a, int b) = "foo(uint32,int256)" +// function foo(uint32 a, int b) = "foo(uint32,int256)" // // Please note that "int" is substitute for its canonical representation "int256" func (method Method) Sig() string { @@ -50,7 +61,7 @@ func (method Method) Sig() string { for i, input := range method.Inputs { types[i] = input.Type.String() } - return fmt.Sprintf("%v(%v)", method.Name, strings.Join(types, ",")) + return fmt.Sprintf("%v(%v)", method.RawName, strings.Join(types, ",")) } func (method Method) String() string { @@ -69,9 +80,11 @@ func (method Method) String() string { if method.Const { constant = "constant " } - return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", ")) + return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", ")) } -func (method Method) Id() []byte { +// ID returns the canonical representation of the method's signature used by the +// abi definition to identify method names and types. +func (method Method) ID() []byte { return crypto.Keccak256([]byte(method.Sig()))[:4] } 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 1b0bb0049..73ca8fa2b 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go @@ -31,6 +31,14 @@ func indirect(v reflect.Value) reflect.Value { return v } +// indirectInterfaceOrPtr recursively dereferences the value until value is not interface. +func indirectInterfaceOrPtr(v reflect.Value) reflect.Value { + if (v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr) && v.Elem().IsValid() { + return indirect(v.Elem()) + } + return v +} + // reflectIntKind returns the reflect using the given size and // unsignedness. func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) { @@ -74,7 +82,7 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value { func set(dst, src reflect.Value) error { dstType, srcType := dst.Type(), src.Type() switch { - case dstType.Kind() == reflect.Interface: + case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): return set(dst.Elem(), src) case dstType.Kind() == reflect.Ptr && dstType.Elem() != derefbigT: return set(dst.Elem(), src) 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 26151dbd3..597d31439 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go @@ -68,7 +68,6 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { if strings.Count(t, "[") != strings.Count(t, "]") { return Type{}, fmt.Errorf("invalid arg type in abi") } - typ.stringKind = t // if there are brackets, get ready to go into slice/array mode and @@ -92,9 +91,7 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { typ.Kind = reflect.Slice typ.Elem = &embeddedType typ.Type = reflect.SliceOf(embeddedType.Type) - if embeddedType.T == TupleTy { - typ.stringKind = embeddedType.stringKind + sliced - } + typ.stringKind = embeddedType.stringKind + sliced } else if len(intz) == 1 { // is a array typ.T = ArrayTy @@ -105,9 +102,7 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) } typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type) - if embeddedType.T == TupleTy { - typ.stringKind = embeddedType.stringKind + sliced - } + typ.stringKind = embeddedType.stringKind + sliced } else { return Type{}, fmt.Errorf("invalid formatting of array type") } @@ -188,6 +183,7 @@ func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) { fields = append(fields, reflect.StructField{ Name: ToCamelCase(c.Name), // reflect.StructOf will panic for any exported field. Type: cType.Type, + Tag: reflect.StructTag("json:\"" + c.Name + "\""), }) elems = append(elems, &cType) names = append(names, c.Name) 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 8406b09c8..b2e61d06c 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go @@ -269,7 +269,7 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err totalSize.Add(totalSize, bigOffsetEnd) totalSize.Add(totalSize, lengthBig) if totalSize.BitLen() > 63 { - return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize) + return 0, 0, fmt.Errorf("abi: length larger than int64: %v", totalSize) } if totalSize.Cmp(outputLength) > 0 { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go b/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go index cb1eae281..bf5190ad9 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/accounts.go @@ -18,12 +18,14 @@ package accounts import ( + "fmt" "math/big" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + "golang.org/x/crypto/sha3" ) // Account represents an Ethereum account located at a specific location defined @@ -33,6 +35,13 @@ type Account struct { URL URL `json:"url"` // Optional resource locator within a backend } +const ( + MimetypeDataWithValidator = "data/validator" + MimetypeTypedData = "data/typed" + MimetypeClique = "application/x-clique-header" + MimetypeTextPlain = "text/plain" +) + // Wallet represents a software or hardware wallet that might contain one or more // accounts (derived from the same seed). type Wallet interface { @@ -83,12 +92,34 @@ type Wallet interface { // opposed to decending into a child path to allow discovering accounts starting // from non zero components. // + // Some hardware wallets switched derivation paths through their evolution, so + // this method supports providing multiple bases to discover old user accounts + // too. Only the last base will be used to derive the next empty account. + // // You can disable automatic account discovery by calling SelfDerive with a nil // chain state reader. - SelfDerive(base DerivationPath, chain ethereum.ChainStateReader) + SelfDerive(bases []DerivationPath, chain ethereum.ChainStateReader) - // SignHash requests the wallet to sign the given hash. + // SignData requests the wallet to sign the hash of the given data + // It looks up the account specified either solely via its address contained within, + // or optionally with the aid of any location metadata from the embedded URL field. // + // If the wallet requires additional authentication to sign the request (e.g. + // a password to decrypt the account, or a PIN code o verify the transaction), + // an AuthNeededError instance will be returned, containing infos for the user + // about which fields or actions are needed. The user may retry by providing + // the needed details via SignDataWithPassphrase, or by other means (e.g. unlock + // the account in a keystore). + SignData(account Account, mimeType string, data []byte) ([]byte, error) + + // SignDataWithPassphrase is identical to SignData, but also takes a password + // NOTE: there's an chance that an erroneous call might mistake the two strings, and + // supply password in the mimetype field, or vice versa. Thus, an implementation + // should never echo the mimetype or return the mimetype in the error-response + SignDataWithPassphrase(account Account, passphrase, mimeType string, data []byte) ([]byte, error) + + // SignText requests the wallet to sign the hash of a given piece of data, prefixed + // by the Ethereum prefix scheme // It looks up the account specified either solely via its address contained within, // or optionally with the aid of any location metadata from the embedded URL field. // @@ -98,7 +129,10 @@ type Wallet interface { // about which fields or actions are needed. The user may retry by providing // the needed details via SignHashWithPassphrase, or by other means (e.g. unlock // the account in a keystore). - SignHash(account Account, hash []byte) ([]byte, error) + SignText(account Account, text []byte) ([]byte, error) + + // SignTextWithPassphrase is identical to Signtext, but also takes a password + SignTextWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error) // SignTx requests the wallet to sign the given transaction. // @@ -113,18 +147,7 @@ type Wallet interface { // the account in a keystore). SignTx(account Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) - // SignHashWithPassphrase requests the wallet to sign the given hash with the - // given passphrase as extra authentication information. - // - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. - SignHashWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error) - - // SignTxWithPassphrase requests the wallet to sign the given transaction, with the - // given passphrase as extra authentication information. - // - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. + // SignTxWithPassphrase is identical to SignTx, but also takes a password SignTxWithPassphrase(account Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) } @@ -148,6 +171,32 @@ type Backend interface { Subscribe(sink chan<- WalletEvent) event.Subscription } +// TextHash 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 TextHash(data []byte) []byte { + hash, _ := TextAndHash(data) + return hash +} + +// TextAndHash 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 TextAndHash(data []byte) ([]byte, string) { + msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data)) + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(msg)) + return hasher.Sum(nil), msg +} + // WalletEventType represents the different event types that can be fired by // the wallet subscription subsystem. type WalletEventType int diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/errors.go b/vendor/github.com/ethereum/go-ethereum/accounts/errors.go index 40b21ed17..2fed35f9d 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/errors.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/errors.go @@ -35,7 +35,7 @@ var ErrNotSupported = errors.New("not supported") // ErrInvalidPassphrase is returned when a decryption operation receives a bad // passphrase. -var ErrInvalidPassphrase = errors.New("invalid passphrase") +var ErrInvalidPassphrase = errors.New("invalid password") // ErrWalletAlreadyOpen is returned if a wallet is attempted to be opened the // second time. diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go b/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go new file mode 100644 index 000000000..6089ca984 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/external/backend.go @@ -0,0 +1,231 @@ +// Copyright 2019 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 external + +import ( + "fmt" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/signer/core" +) + +type ExternalBackend struct { + signers []accounts.Wallet +} + +func (eb *ExternalBackend) Wallets() []accounts.Wallet { + return eb.signers +} + +func NewExternalBackend(endpoint string) (*ExternalBackend, error) { + signer, err := NewExternalSigner(endpoint) + if err != nil { + return nil, err + } + return &ExternalBackend{ + signers: []accounts.Wallet{signer}, + }, nil +} + +func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + <-quit + return nil + }) +} + +// ExternalSigner provides an API to interact with an external signer (clef) +// It proxies request to the external signer while forwarding relevant +// request headers +type ExternalSigner struct { + client *rpc.Client + endpoint string + status string + cacheMu sync.RWMutex + cache []accounts.Account +} + +func NewExternalSigner(endpoint string) (*ExternalSigner, error) { + client, err := rpc.Dial(endpoint) + if err != nil { + return nil, err + } + extsigner := &ExternalSigner{ + client: client, + endpoint: endpoint, + } + // Check if reachable + version, err := extsigner.pingVersion() + if err != nil { + return nil, err + } + extsigner.status = fmt.Sprintf("ok [version=%v]", version) + return extsigner, nil +} + +func (api *ExternalSigner) URL() accounts.URL { + return accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + } +} + +func (api *ExternalSigner) Status() (string, error) { + return api.status, nil +} + +func (api *ExternalSigner) Open(passphrase string) error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Close() error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Accounts() []accounts.Account { + var accnts []accounts.Account + res, err := api.listAccounts() + if err != nil { + log.Error("account listing failed", "error", err) + return accnts + } + for _, addr := range res { + accnts = append(accnts, accounts.Account{ + URL: accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + }, + Address: addr, + }) + } + api.cacheMu.Lock() + api.cache = accnts + api.cacheMu.Unlock() + return accnts +} + +func (api *ExternalSigner) Contains(account accounts.Account) bool { + api.cacheMu.RLock() + defer api.cacheMu.RUnlock() + for _, a := range api.cache { + if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) { + return true + } + } + return false +} + +func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + return accounts.Account{}, fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { + log.Error("operation SelfDerive not supported on external signers") +} + +func (api *ExternalSigner) signHash(account accounts.Account, hash []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("operation not supported on external signers") +} + +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + mimeType, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(data)); err != nil { + return nil, err + } + // If V is on 27/28-form, convert to to 0/1 for Clique + if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) { + res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use + } + return res, nil +} + +func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + accounts.MimetypeTextPlain, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(text)); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + res := ethapi.SignTransactionResult{} + data := hexutil.Bytes(tx.Data()) + var to *common.MixedcaseAddress + if tx.To() != nil { + t := common.NewMixedcaseAddress(*tx.To()) + to = &t + } + args := &core.SendTxArgs{ + Data: &data, + Nonce: hexutil.Uint64(tx.Nonce()), + Value: hexutil.Big(*tx.Value()), + Gas: hexutil.Uint64(tx.Gas()), + GasPrice: hexutil.Big(*tx.GasPrice()), + To: to, + From: common.NewMixedcaseAddress(account.Address), + } + if err := api.client.Call(&res, "account_signTransaction", args); err != nil { + return nil, err + } + return res.Tx, nil +} + +func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("password-operations not supported on external signers") +} + +func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + return nil, fmt.Errorf("password-operations not supported on external signers") +} +func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return nil, fmt.Errorf("password-operations not supported on external signers") +} + +func (api *ExternalSigner) listAccounts() ([]common.Address, error) { + var res []common.Address + if err := api.client.Call(&res, "account_list"); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) pingVersion() (string, error) { + var v string + if err := api.client.Call(&v, "account_version"); err != nil { + return "", err + } + return v, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/hd.go b/vendor/github.com/ethereum/go-ethereum/accounts/hd.go index 6ed631807..75c476110 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/hd.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/hd.go @@ -17,6 +17,7 @@ package accounts import ( + "encoding/json" "errors" "fmt" "math" @@ -34,10 +35,10 @@ var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, // at m/44'/60'/0'/0/1, etc. var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0} -// DefaultLedgerBaseDerivationPath is the base path from which custom derivation endpoints -// are incremented. As such, the first account will be at m/44'/60'/0'/0, the second -// at m/44'/60'/0'/1, etc. -var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0} +// LegacyLedgerBaseDerivationPath is the legacy base path from which custom derivation +// endpoints are incremented. As such, the first account will be at m/44'/60'/0'/0, the +// second at m/44'/60'/0'/1, etc. +var LegacyLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0} // DerivationPath represents the computer friendly version of a hierarchical // deterministic wallet account derivaion path. @@ -133,3 +134,19 @@ func (path DerivationPath) String() string { } return result } + +// MarshalJSON turns a derivation path into its json-serialized string +func (path DerivationPath) MarshalJSON() ([]byte, error) { + return json.Marshal(path.String()) +} + +// UnmarshalJSON a json-serialized string back into a derivation path +func (path *DerivationPath) UnmarshalJSON(b []byte) error { + var dp string + var err error + if err = json.Unmarshal(b, &dp); err != nil { + return err + } + *path, err = ParseDerivationPath(dp) + return err +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/key.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/key.go index 03f7d59ea..e57ff5022 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/key.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/key.go @@ -53,7 +53,6 @@ type Key struct { // SubAccountIndex is DEPRECATED // It was use in Status to keep track of the number of sub-account created // before having multi-account support. - // next index to be used for sub-account child derivation SubAccountIndex uint32 } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go index 41d24f88d..c1d8ca187 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/keystore.go @@ -25,6 +25,7 @@ import ( crand "crypto/rand" "errors" "fmt" + "github.com/pborman/uuid" "math/big" "os" "path/filepath" @@ -38,14 +39,13 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" - "github.com/pborman/uuid" "github.com/status-im/status-go/extkeys" ) var ( ErrLocked = accounts.NewAuthNeededError("password or unlock") ErrNoMatch = errors.New("no key for given address or file") - ErrDecrypt = errors.New("could not decrypt key with given passphrase") + ErrDecrypt = errors.New("could not decrypt key with given password") ) // KeyStoreType is the reflect type of a keystore backend. @@ -139,8 +139,10 @@ func (ks *KeyStore) refreshWallets() { accs := ks.cache.accounts() // Transform the current list of wallets into the new one - wallets := make([]accounts.Wallet, 0, len(accs)) - events := []accounts.WalletEvent{} + var ( + wallets = make([]accounts.Wallet, 0, len(accs)) + events []accounts.WalletEvent + ) for _, account := range accs { // Drop wallets while they were in front of the next account diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/passphrase.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/passphrase.go index e2512c6e8..7d859a8c1 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/passphrase.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/passphrase.go @@ -38,6 +38,7 @@ import ( "os" "path/filepath" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" @@ -98,9 +99,9 @@ func (ks keyStorePassphrase) GetKey(addr common.Address, filename, auth string) } // StoreKey generates a key, encrypts with 'auth' and stores in the given directory -func StoreKey(dir, auth string, scryptN, scryptP int) (common.Address, error) { +func StoreKey(dir, auth string, scryptN, scryptP int) (accounts.Account, error) { _, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP, false}, rand.Reader, auth) - return a.Address, err + return a, err } func (ks keyStorePassphrase) StoreKey(filename string, key *Key, auth string) error { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go index 2f774cc94..498067d49 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/wallet.go @@ -22,6 +22,7 @@ import ( ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ) // keystoreWallet implements the accounts.Wallet interface for the original @@ -76,13 +77,14 @@ func (w *keystoreWallet) Derive(path accounts.DerivationPath, pin bool) (account // SelfDerive implements accounts.Wallet, but is a noop for plain wallets since // there is no notion of hierarchical account derivation for plain keystore accounts. -func (w *keystoreWallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {} +func (w *keystoreWallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { +} -// SignHash implements accounts.Wallet, attempting to sign the given hash with +// signHash attempts to sign the given hash with // the given account. If the wallet does not wrap this particular account, an // error is returned to avoid account leakage (even though in theory we may be // able to sign via our shared keystore backend). -func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) { +func (w *keystoreWallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { // Make sure the requested account is contained within if !w.Contains(account) { return nil, accounts.ErrUnknownAccount @@ -91,6 +93,36 @@ func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte return w.keystore.SignHash(account, hash) } +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *keystoreWallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + return w.signHash(account, crypto.Keccak256(data)) +} + +// SignDataWithPassphrase signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *keystoreWallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + // Account seems valid, request the keystore to sign + return w.keystore.SignHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) +} + +func (w *keystoreWallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + return w.signHash(account, accounts.TextHash(text)) +} + +// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the +// given hash with the given account using passphrase as extra authentication. +func (w *keystoreWallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + // Account seems valid, request the keystore to sign + return w.keystore.SignHashWithPassphrase(account, passphrase, accounts.TextHash(text)) +} + // SignTx implements accounts.Wallet, attempting to sign the given transaction // with the given account. If the wallet does not wrap this particular account, // an error is returned to avoid account leakage (even though in theory we may @@ -104,17 +136,6 @@ func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, return w.keystore.SignTx(account, tx, chainID) } -// SignHashWithPassphrase implements accounts.Wallet, attempting to sign the -// given hash with the given account using passphrase as extra authentication. -func (w *keystoreWallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignHashWithPassphrase(account, passphrase, hash) -} - // SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given // transaction with the given account using passphrase as extra authentication. func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch.go index bbcfb9925..d6ef53327 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build darwin,!ios freebsd linux,!arm64 netbsd solaris +// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris package keystore diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch_fallback.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch_fallback.go index 7c5e9cb2e..de0e87f8a 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch_fallback.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/watch_fallback.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris +// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris // This is the fallback implementation of directory watching. // It is used on unsupported platforms. diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/manager.go b/vendor/github.com/ethereum/go-ethereum/accounts/manager.go index 96ca298fc..731d12ea3 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/manager.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/manager.go @@ -21,12 +21,22 @@ import ( "sort" "sync" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" ) +// Config contains the settings of the global account manager. +// +// TODO(rjl493456442, karalabe, holiman): Get rid of this when account management +// is removed in favor of Clef. +type Config struct { + InsecureUnlockAllowed bool // Whether account unlocking in insecure environment is allowed +} + // Manager is an overarching account manager that can communicate with various // backends for signing transactions. type Manager struct { + config *Config // Global account manager configurations backends map[reflect.Type][]Backend // Index of backends currently registered updaters []event.Subscription // Wallet update subscriptions for all backends updates chan WalletEvent // Subscription sink for backend wallet changes @@ -40,7 +50,7 @@ type Manager struct { // NewManager creates a generic account manager to sign transaction via various // supported backends. -func NewManager(backends ...Backend) *Manager { +func NewManager(config *Config, backends ...Backend) *Manager { // Retrieve the initial list of wallets from the backends and sort by URL var wallets []Wallet for _, backend := range backends { @@ -55,6 +65,7 @@ func NewManager(backends ...Backend) *Manager { } // Assemble the account manager and return am := &Manager{ + config: config, backends: make(map[reflect.Type][]Backend), updaters: subs, updates: updates, @@ -77,6 +88,11 @@ func (am *Manager) Close() error { return <-errc } +// Config returns the configuration of account manager. +func (am *Manager) Config() *Config { + return am.config +} + // update is the wallet event loop listening for notifications from the backends // and updating the cache of wallets. func (am *Manager) update() { @@ -147,6 +163,20 @@ func (am *Manager) Wallet(url string) (Wallet, error) { return nil, ErrUnknownWallet } +// Accounts returns all account addresses of all wallets within the account manager +func (am *Manager) Accounts() []common.Address { + am.lock.RLock() + defer am.lock.RUnlock() + + addresses := make([]common.Address, 0) // return [] instead of nil if empty + for _, wallet := range am.wallets { + for _, account := range wallet.Accounts() { + addresses = append(addresses, account.Address) + } + } + return addresses +} + // Find attempts to locate the wallet corresponding to a specific account. Since // accounts can be dynamically added to and removed from wallets, this method has // a linear runtime in the number of wallets. diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/README.md b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/README.md new file mode 100644 index 000000000..cfca916b3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/README.md @@ -0,0 +1,102 @@ +# Using the smartcard wallet + +## Requirements + + * A USB smartcard reader + * A keycard that supports the status app + * PCSCD version 4.3 running on your system **Only version 4.3 is currently supported** + +## Preparing the smartcard + + **WARNING: FOILLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS** + + You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap) + + You also need to make sure that the PCSC daemon is running on your system. + + Then, you can install the application to the card by typing: + + ``` + keycard install -a keycard_v2.2.1.cap && keycard init + ``` + + At the end of this process, you will be provided with a PIN, a PUK and a pairing password. Write them down, you'll need them shortly. + + Start `geth` with the `console` command. You will notice the following warning: + + ``` + WARN [04-09|16:58:38.898] Failed to open wallet url=keycard://044def09 err="smartcard: pairing password needed" + ``` + + Write down the URL (`keycard://044def09` in this example). Then ask `geth` to open the wallet: + + ``` + > personal.openWallet("keycard://044def09") + Please enter the pairing password: + ``` + + Enter the pairing password that you have received during card initialization. Same with the PIN that you will subsequently be + asked for. + + If everything goes well, you should see your new account when typing `personal` on the console: + + ``` + > personal + WARN [04-09|17:02:07.330] Smartcard wallet account derivation failed url=keycard://044def09 err="Unexpected response status Cla=0x80, Ins=0xd1, Sw=0x6985" + { + listAccounts: [], + listWallets: [{ + status: "Empty, waiting for initialization", + url: "keycard://044def09" + }], + ... + } + ``` + + So the communication with the card is working, but there is no key associated with this wallet. Let's create it: + + ``` + > personal.initializeWallet("keycard://044def09") + "tilt ... impact" + ``` + + You should get a list of words, this is your seed so write them down. Your wallet should now be initialized: + + ``` + > personal.listWallets + [{ + accounts: [{ + address: "0x678b7cd55c61917defb23546a41803c5bfefbc7a", + url: "keycard://044d/m/44'/60'/0'/0/0" + }], + status: "Online", + url: "keycard://044def09" + }] + ``` + + You're all set! + +## Usage + + 1. Start `geth` with the `console` command + 2. Check the card's URL by checking `personal.listWallets`: + +``` + listWallets: [{ + status: "Online, can derive public keys", + url: "keycard://a4d73015" + }] +``` + + 3. Open the wallet, you will be prompted for your pairing password, then PIN: + +``` +personal.openWallet("keycard://a4d73015") +``` + + 4. Check that creation was successful by typing e.g. `personal`. Then use it like a regular wallet. + +## Known issues + + * Starting geth with a valid card seems to make firefox crash. + * PCSC version 4.4 should work, but is currently untested diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/apdu.go b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/apdu.go new file mode 100644 index 000000000..bd3660604 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/apdu.go @@ -0,0 +1,87 @@ +// 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 scwallet + +import ( + "bytes" + "encoding/binary" + "fmt" +) + +// commandAPDU represents an application data unit sent to a smartcard. +type commandAPDU struct { + Cla, Ins, P1, P2 uint8 // Class, Instruction, Parameter 1, Parameter 2 + Data []byte // Command data + Le uint8 // Command data length +} + +// serialize serializes a command APDU. +func (ca commandAPDU) serialize() ([]byte, error) { + buf := new(bytes.Buffer) + + if err := binary.Write(buf, binary.BigEndian, ca.Cla); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, ca.Ins); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, ca.P1); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, ca.P2); err != nil { + return nil, err + } + if len(ca.Data) > 0 { + if err := binary.Write(buf, binary.BigEndian, uint8(len(ca.Data))); err != nil { + return nil, err + } + if err := binary.Write(buf, binary.BigEndian, ca.Data); err != nil { + return nil, err + } + } + if err := binary.Write(buf, binary.BigEndian, ca.Le); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// responseAPDU represents an application data unit received from a smart card. +type responseAPDU struct { + Data []byte // response data + Sw1, Sw2 uint8 // status words 1 and 2 +} + +// deserialize deserializes a response APDU. +func (ra *responseAPDU) deserialize(data []byte) error { + if len(data) < 2 { + return fmt.Errorf("can not deserialize data: payload too short (%d < 2)", len(data)) + } + + ra.Data = make([]byte, len(data)-2) + + buf := bytes.NewReader(data) + if err := binary.Read(buf, binary.BigEndian, &ra.Data); err != nil { + return err + } + if err := binary.Read(buf, binary.BigEndian, &ra.Sw1); err != nil { + return err + } + if err := binary.Read(buf, binary.BigEndian, &ra.Sw2); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/hub.go b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/hub.go new file mode 100644 index 000000000..5f939c658 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/hub.go @@ -0,0 +1,302 @@ +// 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 . + +// This package implements support for smartcard-based hardware wallets such as +// the one written by Status: https://github.com/status-im/hardware-wallet +// +// This implementation of smartcard wallets have a different interaction process +// to other types of hardware wallet. The process works like this: +// +// 1. (First use with a given client) Establish a pairing between hardware +// wallet and client. This requires a secret value called a 'pairing password'. +// You can pair with an unpaired wallet with `personal.openWallet(URI, pairing password)`. +// 2. (First use only) Initialize the wallet, which generates a keypair, stores +// it on the wallet, and returns it so the user can back it up. You can +// initialize a wallet with `personal.initializeWallet(URI)`. +// 3. Connect to the wallet using the pairing information established in step 1. +// You can connect to a paired wallet with `personal.openWallet(URI, PIN)`. +// 4. Interact with the wallet as normal. + +package scwallet + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "sort" + "sync" + "time" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" + pcsc "github.com/gballet/go-libpcsclite" +) + +// Scheme is the URI prefix for smartcard wallets. +const Scheme = "keycard" + +// refreshCycle is the maximum time between wallet refreshes (if USB hotplug +// notifications don't work). +const refreshCycle = time.Second + +// refreshThrottling is the minimum time between wallet refreshes to avoid thrashing. +const refreshThrottling = 500 * time.Millisecond + +// smartcardPairing contains information about a smart card we have paired with +// or might pair with the hub. +type smartcardPairing struct { + PublicKey []byte `json:"publicKey"` + PairingIndex uint8 `json:"pairingIndex"` + PairingKey []byte `json:"pairingKey"` + Accounts map[common.Address]accounts.DerivationPath `json:"accounts"` +} + +// Hub is a accounts.Backend that can find and handle generic PC/SC hardware wallets. +type Hub struct { + scheme string // Protocol scheme prefixing account and wallet URLs. + + context *pcsc.Client + datadir string + pairings map[string]smartcardPairing + + refreshed time.Time // Time instance when the list of wallets was last refreshed + wallets map[string]*Wallet // Mapping from reader names to wallet instances + updateFeed event.Feed // Event feed to notify wallet additions/removals + updateScope event.SubscriptionScope // Subscription scope tracking current live listeners + updating bool // Whether the event notification loop is running + + quit chan chan error + + stateLock sync.RWMutex // Protects the internals of the hub from racey access +} + +func (hub *Hub) readPairings() error { + hub.pairings = make(map[string]smartcardPairing) + pairingFile, err := os.Open(filepath.Join(hub.datadir, "smartcards.json")) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + + pairingData, err := ioutil.ReadAll(pairingFile) + if err != nil { + return err + } + var pairings []smartcardPairing + if err := json.Unmarshal(pairingData, &pairings); err != nil { + return err + } + + for _, pairing := range pairings { + hub.pairings[string(pairing.PublicKey)] = pairing + } + return nil +} + +func (hub *Hub) writePairings() error { + pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } + defer pairingFile.Close() + + pairings := make([]smartcardPairing, 0, len(hub.pairings)) + for _, pairing := range hub.pairings { + pairings = append(pairings, pairing) + } + + pairingData, err := json.Marshal(pairings) + if err != nil { + return err + } + + if _, err := pairingFile.Write(pairingData); err != nil { + return err + } + + return nil +} + +func (hub *Hub) pairing(wallet *Wallet) *smartcardPairing { + if pairing, ok := hub.pairings[string(wallet.PublicKey)]; ok { + return &pairing + } + return nil +} + +func (hub *Hub) setPairing(wallet *Wallet, pairing *smartcardPairing) error { + if pairing == nil { + delete(hub.pairings, string(wallet.PublicKey)) + } else { + hub.pairings[string(wallet.PublicKey)] = *pairing + } + return hub.writePairings() +} + +// NewHub creates a new hardware wallet manager for smartcards. +func NewHub(daemonPath string, scheme string, datadir string) (*Hub, error) { + context, err := pcsc.EstablishContext(daemonPath, pcsc.ScopeSystem) + if err != nil { + return nil, err + } + hub := &Hub{ + scheme: scheme, + context: context, + datadir: datadir, + wallets: make(map[string]*Wallet), + quit: make(chan chan error), + } + if err := hub.readPairings(); err != nil { + return nil, err + } + hub.refreshWallets() + return hub, nil +} + +// Wallets implements accounts.Backend, returning all the currently tracked smart +// cards that appear to be hardware wallets. +func (hub *Hub) Wallets() []accounts.Wallet { + // Make sure the list of wallets is up to date + hub.refreshWallets() + + hub.stateLock.RLock() + defer hub.stateLock.RUnlock() + + cpy := make([]accounts.Wallet, 0, len(hub.wallets)) + for _, wallet := range hub.wallets { + cpy = append(cpy, wallet) + } + sort.Sort(accounts.WalletsByURL(cpy)) + return cpy +} + +// refreshWallets scans the devices attached to the machine and updates the +// list of wallets based on the found devices. +func (hub *Hub) refreshWallets() { + // Don't scan the USB like crazy it the user fetches wallets in a loop + hub.stateLock.RLock() + elapsed := time.Since(hub.refreshed) + hub.stateLock.RUnlock() + + if elapsed < refreshThrottling { + return + } + // Retrieve all the smart card reader to check for cards + readers, err := hub.context.ListReaders() + if err != nil { + // This is a perverted hack, the scard library returns an error if no card + // readers are present instead of simply returning an empty list. We don't + // want to fill the user's log with errors, so filter those out. + if err.Error() != "scard: Cannot find a smart card reader." { + log.Error("Failed to enumerate smart card readers", "err", err) + return + } + } + // Transform the current list of wallets into the new one + hub.stateLock.Lock() + + events := []accounts.WalletEvent{} + seen := make(map[string]struct{}) + + for _, reader := range readers { + // Mark the reader as present + seen[reader] = struct{}{} + + // If we alreay know about this card, skip to the next reader, otherwise clean up + if wallet, ok := hub.wallets[reader]; ok { + if err := wallet.ping(); err == nil { + continue + } + wallet.Close() + events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) + delete(hub.wallets, reader) + } + // New card detected, try to connect to it + card, err := hub.context.Connect(reader, pcsc.ShareShared, pcsc.ProtocolAny) + if err != nil { + log.Debug("Failed to open smart card", "reader", reader, "err", err) + continue + } + wallet := NewWallet(hub, card) + if err = wallet.connect(); err != nil { + log.Debug("Failed to connect to smart card", "reader", reader, "err", err) + card.Disconnect(pcsc.LeaveCard) + continue + } + // Card connected, start tracking in amongs the wallets + hub.wallets[reader] = wallet + events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) + } + // Remove any wallets no longer present + for reader, wallet := range hub.wallets { + if _, ok := seen[reader]; !ok { + wallet.Close() + events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) + delete(hub.wallets, reader) + } + } + hub.refreshed = time.Now() + hub.stateLock.Unlock() + + for _, event := range events { + hub.updateFeed.Send(event) + } +} + +// Subscribe implements accounts.Backend, creating an async subscription to +// receive notifications on the addition or removal of smart card wallets. +func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { + // We need the mutex to reliably start/stop the update loop + hub.stateLock.Lock() + defer hub.stateLock.Unlock() + + // Subscribe the caller and track the subscriber count + sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink)) + + // Subscribers require an active notification loop, start it + if !hub.updating { + hub.updating = true + go hub.updater() + } + return sub +} + +// updater is responsible for maintaining an up-to-date list of wallets managed +// by the smart card hub, and for firing wallet addition/removal events. +func (hub *Hub) updater() { + for { + // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout + // <-hub.changes + time.Sleep(refreshCycle) + + // Run the wallet refresher + hub.refreshWallets() + + // If all our subscribers left, stop the updater + hub.stateLock.Lock() + if hub.updateScope.Count() == 0 { + hub.updating = false + hub.stateLock.Unlock() + return + } + hub.stateLock.Unlock() + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/securechannel.go b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/securechannel.go new file mode 100644 index 000000000..fad876a01 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/securechannel.go @@ -0,0 +1,346 @@ +// 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 scwallet + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "fmt" + + "github.com/ethereum/go-ethereum/crypto" + pcsc "github.com/gballet/go-libpcsclite" + "github.com/wsddn/go-ecdh" + "golang.org/x/crypto/pbkdf2" + "golang.org/x/text/unicode/norm" +) + +const ( + maxPayloadSize = 223 + pairP1FirstStep = 0 + pairP1LastStep = 1 + + scSecretLength = 32 + scBlockSize = 16 + + insOpenSecureChannel = 0x10 + insMutuallyAuthenticate = 0x11 + insPair = 0x12 + insUnpair = 0x13 + + pairingSalt = "Keycard Pairing Password Salt" +) + +// SecureChannelSession enables secure communication with a hardware wallet. +type SecureChannelSession struct { + card *pcsc.Card // A handle to the smartcard for communication + secret []byte // A shared secret generated from our ECDSA keys + publicKey []byte // Our own ephemeral public key + PairingKey []byte // A permanent shared secret for a pairing, if present + sessionEncKey []byte // The current session encryption key + sessionMacKey []byte // The current session MAC key + iv []byte // The current IV + PairingIndex uint8 // The pairing index +} + +// NewSecureChannelSession creates a new secure channel for the given card and public key. +func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSession, error) { + // Generate an ECDSA keypair for ourselves + gen := ecdh.NewEllipticECDH(crypto.S256()) + private, public, err := gen.GenerateKey(rand.Reader) + if err != nil { + return nil, err + } + + cardPublic, ok := gen.Unmarshal(keyData) + if !ok { + return nil, fmt.Errorf("Could not unmarshal public key from card") + } + + secret, err := gen.GenerateSharedSecret(private, cardPublic) + if err != nil { + return nil, err + } + + return &SecureChannelSession{ + card: card, + secret: secret, + publicKey: gen.Marshal(public), + }, nil +} + +// Pair establishes a new pairing with the smartcard. +func (s *SecureChannelSession) Pair(pairingPassword []byte) error { + secretHash := pbkdf2.Key(norm.NFKD.Bytes(pairingPassword), norm.NFKD.Bytes([]byte(pairingSalt)), 50000, 32, sha256.New) + + challenge := make([]byte, 32) + if _, err := rand.Read(challenge); err != nil { + return err + } + + response, err := s.pair(pairP1FirstStep, challenge) + if err != nil { + return err + } + + md := sha256.New() + md.Write(secretHash[:]) + md.Write(challenge) + + expectedCryptogram := md.Sum(nil) + cardCryptogram := response.Data[:32] + cardChallenge := response.Data[32:64] + + if !bytes.Equal(expectedCryptogram, cardCryptogram) { + return fmt.Errorf("Invalid card cryptogram %v != %v", expectedCryptogram, cardCryptogram) + } + + md.Reset() + md.Write(secretHash[:]) + md.Write(cardChallenge) + response, err = s.pair(pairP1LastStep, md.Sum(nil)) + if err != nil { + return err + } + + md.Reset() + md.Write(secretHash[:]) + md.Write(response.Data[1:]) + s.PairingKey = md.Sum(nil) + s.PairingIndex = response.Data[0] + + return nil +} + +// Unpair disestablishes an existing pairing. +func (s *SecureChannelSession) Unpair() error { + if s.PairingKey == nil { + return fmt.Errorf("Cannot unpair: not paired") + } + + _, err := s.transmitEncrypted(claSCWallet, insUnpair, s.PairingIndex, 0, []byte{}) + if err != nil { + return err + } + s.PairingKey = nil + // Close channel + s.iv = nil + return nil +} + +// Open initializes the secure channel. +func (s *SecureChannelSession) Open() error { + if s.iv != nil { + return fmt.Errorf("Session already opened") + } + + response, err := s.open() + if err != nil { + return err + } + + // Generate the encryption/mac key by hashing our shared secret, + // pairing key, and the first bytes returned from the Open APDU. + md := sha512.New() + md.Write(s.secret) + md.Write(s.PairingKey) + md.Write(response.Data[:scSecretLength]) + keyData := md.Sum(nil) + s.sessionEncKey = keyData[:scSecretLength] + s.sessionMacKey = keyData[scSecretLength : scSecretLength*2] + + // The IV is the last bytes returned from the Open APDU. + s.iv = response.Data[scSecretLength:] + + return s.mutuallyAuthenticate() +} + +// mutuallyAuthenticate is an internal method to authenticate both ends of the +// connection. +func (s *SecureChannelSession) mutuallyAuthenticate() error { + data := make([]byte, scSecretLength) + if _, err := rand.Read(data); err != nil { + return err + } + + response, err := s.transmitEncrypted(claSCWallet, insMutuallyAuthenticate, 0, 0, data) + if err != nil { + return err + } + if response.Sw1 != 0x90 || response.Sw2 != 0x00 { + return fmt.Errorf("Got unexpected response from MUTUALLY_AUTHENTICATE: 0x%x%x", response.Sw1, response.Sw2) + } + + if len(response.Data) != scSecretLength { + return fmt.Errorf("Response from MUTUALLY_AUTHENTICATE was %d bytes, expected %d", len(response.Data), scSecretLength) + } + + return nil +} + +// open is an internal method that sends an open APDU. +func (s *SecureChannelSession) open() (*responseAPDU, error) { + return transmit(s.card, &commandAPDU{ + Cla: claSCWallet, + Ins: insOpenSecureChannel, + P1: s.PairingIndex, + P2: 0, + Data: s.publicKey, + Le: 0, + }) +} + +// pair is an internal method that sends a pair APDU. +func (s *SecureChannelSession) pair(p1 uint8, data []byte) (*responseAPDU, error) { + return transmit(s.card, &commandAPDU{ + Cla: claSCWallet, + Ins: insPair, + P1: p1, + P2: 0, + Data: data, + Le: 0, + }) +} + +// transmitEncrypted sends an encrypted message, and decrypts and returns the response. +func (s *SecureChannelSession) transmitEncrypted(cla, ins, p1, p2 byte, data []byte) (*responseAPDU, error) { + if s.iv == nil { + return nil, fmt.Errorf("Channel not open") + } + + data, err := s.encryptAPDU(data) + if err != nil { + return nil, err + } + meta := [16]byte{cla, ins, p1, p2, byte(len(data) + scBlockSize)} + if err = s.updateIV(meta[:], data); err != nil { + return nil, err + } + + fulldata := make([]byte, len(s.iv)+len(data)) + copy(fulldata, s.iv) + copy(fulldata[len(s.iv):], data) + + response, err := transmit(s.card, &commandAPDU{ + Cla: cla, + Ins: ins, + P1: p1, + P2: p2, + Data: fulldata, + }) + if err != nil { + return nil, err + } + + rmeta := [16]byte{byte(len(response.Data))} + rmac := response.Data[:len(s.iv)] + rdata := response.Data[len(s.iv):] + plainData, err := s.decryptAPDU(rdata) + if err != nil { + return nil, err + } + + if err = s.updateIV(rmeta[:], rdata); err != nil { + return nil, err + } + if !bytes.Equal(s.iv, rmac) { + return nil, fmt.Errorf("Invalid MAC in response") + } + + rapdu := &responseAPDU{} + rapdu.deserialize(plainData) + + if rapdu.Sw1 != sw1Ok { + return nil, fmt.Errorf("Unexpected response status Cla=0x%x, Ins=0x%x, Sw=0x%x%x", cla, ins, rapdu.Sw1, rapdu.Sw2) + } + + return rapdu, nil +} + +// encryptAPDU is an internal method that serializes and encrypts an APDU. +func (s *SecureChannelSession) encryptAPDU(data []byte) ([]byte, error) { + if len(data) > maxPayloadSize { + return nil, fmt.Errorf("Payload of %d bytes exceeds maximum of %d", len(data), maxPayloadSize) + } + data = pad(data, 0x80) + + ret := make([]byte, len(data)) + + a, err := aes.NewCipher(s.sessionEncKey) + if err != nil { + return nil, err + } + crypter := cipher.NewCBCEncrypter(a, s.iv) + crypter.CryptBlocks(ret, data) + return ret, nil +} + +// pad applies message padding to a 16 byte boundary. +func pad(data []byte, terminator byte) []byte { + padded := make([]byte, (len(data)/16+1)*16) + copy(padded, data) + padded[len(data)] = terminator + return padded +} + +// decryptAPDU is an internal method that decrypts and deserializes an APDU. +func (s *SecureChannelSession) decryptAPDU(data []byte) ([]byte, error) { + a, err := aes.NewCipher(s.sessionEncKey) + if err != nil { + return nil, err + } + + ret := make([]byte, len(data)) + + crypter := cipher.NewCBCDecrypter(a, s.iv) + crypter.CryptBlocks(ret, data) + return unpad(ret, 0x80) +} + +// unpad strips padding from a message. +func unpad(data []byte, terminator byte) ([]byte, error) { + for i := 1; i <= 16; i++ { + switch data[len(data)-i] { + case 0: + continue + case terminator: + return data[:len(data)-i], nil + default: + return nil, fmt.Errorf("Expected end of padding, got %d", data[len(data)-i]) + } + } + return nil, fmt.Errorf("Expected end of padding, got 0") +} + +// updateIV is an internal method that updates the initialization vector after +// each message exchanged. +func (s *SecureChannelSession) updateIV(meta, data []byte) error { + data = pad(data, 0) + a, err := aes.NewCipher(s.sessionMacKey) + if err != nil { + return err + } + crypter := cipher.NewCBCEncrypter(a, make([]byte, 16)) + crypter.CryptBlocks(meta, meta) + crypter.CryptBlocks(data, data) + // The first 16 bytes of the last block is the MAC + s.iv = data[len(data)-32 : len(data)-16] + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/wallet.go b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/wallet.go new file mode 100644 index 000000000..57b597706 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/scwallet/wallet.go @@ -0,0 +1,1082 @@ +// 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 scwallet + +import ( + "bytes" + "context" + "crypto/hmac" + "crypto/sha256" + "crypto/sha512" + "encoding/asn1" + "encoding/binary" + "errors" + "fmt" + "math/big" + "regexp" + "sort" + "strings" + "sync" + "time" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + pcsc "github.com/gballet/go-libpcsclite" + "github.com/status-im/keycard-go/derivationpath" +) + +// ErrPairingPasswordNeeded is returned if opening the smart card requires pairing with a pairing +// password. In this case, the calling application should request user input to enter +// the pairing password and send it back. +var ErrPairingPasswordNeeded = errors.New("smartcard: pairing password needed") + +// ErrPINNeeded is returned if opening the smart card requires a PIN code. In +// this case, the calling application should request user input to enter the PIN +// and send it back. +var ErrPINNeeded = errors.New("smartcard: pin needed") + +// ErrPINUnblockNeeded is returned if opening the smart card requires a PIN code, +// but all PIN attempts have already been exhausted. In this case the calling +// application should request user input for the PUK and a new PIN code to set +// fo the card. +var ErrPINUnblockNeeded = errors.New("smartcard: pin unblock needed") + +// ErrAlreadyOpen is returned if the smart card is attempted to be opened, but +// there is already a paired and unlocked session. +var ErrAlreadyOpen = errors.New("smartcard: already open") + +// ErrPubkeyMismatch is returned if the public key recovered from a signature +// does not match the one expected by the user. +var ErrPubkeyMismatch = errors.New("smartcard: recovered public key mismatch") + +var ( + appletAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x01, 0x01} + // DerivationSignatureHash is used to derive the public key from the signature of this hash + DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes()) +) + +// List of APDU command-related constants +const ( + claISO7816 = 0 + claSCWallet = 0x80 + + insSelect = 0xA4 + insGetResponse = 0xC0 + sw1GetResponse = 0x61 + sw1Ok = 0x90 + + insVerifyPin = 0x20 + insUnblockPin = 0x22 + insExportKey = 0xC2 + insSign = 0xC0 + insLoadKey = 0xD0 + insDeriveKey = 0xD1 + insStatus = 0xF2 +) + +// List of ADPU command parameters +const ( + P1DeriveKeyFromMaster = uint8(0x00) + P1DeriveKeyFromParent = uint8(0x01) + P1DeriveKeyFromCurrent = uint8(0x10) + statusP1WalletStatus = uint8(0x00) + statusP1Path = uint8(0x01) + signP1PrecomputedHash = uint8(0x01) + signP2OnlyBlock = uint8(0x81) + exportP1Any = uint8(0x00) + exportP2Pubkey = uint8(0x01) +) + +// Minimum time to wait between self derivation attempts, even it the user is +// requesting accounts like crazy. +const selfDeriveThrottling = time.Second + +// Wallet represents a smartcard wallet instance. +type Wallet struct { + Hub *Hub // A handle to the Hub that instantiated this wallet. + PublicKey []byte // The wallet's public key (used for communication and identification, not signing!) + + lock sync.Mutex // Lock that gates access to struct fields and communication with the card + card *pcsc.Card // A handle to the smartcard interface for the wallet. + session *Session // The secure communication session with the card + log log.Logger // Contextual logger to tag the base with its id + + deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported) + deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported) + deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with + deriveReq chan chan struct{} // Channel to request a self-derivation on + deriveQuit chan chan error // Channel to terminate the self-deriver with +} + +// NewWallet constructs and returns a new Wallet instance. +func NewWallet(hub *Hub, card *pcsc.Card) *Wallet { + wallet := &Wallet{ + Hub: hub, + card: card, + } + return wallet +} + +// transmit sends an APDU to the smartcard and receives and decodes the response. +// It automatically handles requests by the card to fetch the return data separately, +// and returns an error if the response status code is not success. +func transmit(card *pcsc.Card, command *commandAPDU) (*responseAPDU, error) { + data, err := command.serialize() + if err != nil { + return nil, err + } + + responseData, _, err := card.Transmit(data) + if err != nil { + return nil, err + } + + response := new(responseAPDU) + if err = response.deserialize(responseData); err != nil { + return nil, err + } + + // Are we being asked to fetch the response separately? + if response.Sw1 == sw1GetResponse && (command.Cla != claISO7816 || command.Ins != insGetResponse) { + return transmit(card, &commandAPDU{ + Cla: claISO7816, + Ins: insGetResponse, + P1: 0, + P2: 0, + Data: nil, + Le: response.Sw2, + }) + } + + if response.Sw1 != sw1Ok { + return nil, fmt.Errorf("Unexpected insecure response status Cla=0x%x, Ins=0x%x, Sw=0x%x%x", command.Cla, command.Ins, response.Sw1, response.Sw2) + } + + return response, nil +} + +// applicationInfo encodes information about the smartcard application - its +// instance UID and public key. +type applicationInfo struct { + InstanceUID []byte `asn1:"tag:15"` + PublicKey []byte `asn1:"tag:0"` +} + +// connect connects to the wallet application and establishes a secure channel with it. +// must be called before any other interaction with the wallet. +func (w *Wallet) connect() error { + w.lock.Lock() + defer w.lock.Unlock() + + appinfo, err := w.doselect() + if err != nil { + return err + } + + channel, err := NewSecureChannelSession(w.card, appinfo.PublicKey) + if err != nil { + return err + } + + w.PublicKey = appinfo.PublicKey + w.log = log.New("url", w.URL()) + w.session = &Session{ + Wallet: w, + Channel: channel, + } + return nil +} + +// doselect is an internal (unlocked) function to send a SELECT APDU to the card. +func (w *Wallet) doselect() (*applicationInfo, error) { + response, err := transmit(w.card, &commandAPDU{ + Cla: claISO7816, + Ins: insSelect, + P1: 4, + P2: 0, + Data: appletAID, + }) + if err != nil { + return nil, err + } + + appinfo := new(applicationInfo) + if _, err := asn1.UnmarshalWithParams(response.Data, appinfo, "tag:4"); err != nil { + return nil, err + } + return appinfo, nil +} + +// ping checks the card's status and returns an error if unsuccessful. +func (w *Wallet) ping() error { + w.lock.Lock() + defer w.lock.Unlock() + + // We can't ping if not paired + if !w.session.paired() { + return nil + } + if _, err := w.session.walletStatus(); err != nil { + return err + } + return nil +} + +// release releases any resources held by an open wallet instance. +func (w *Wallet) release() error { + if w.session != nil { + return w.session.release() + } + return nil +} + +// pair is an internal (unlocked) function for establishing a new pairing +// with the wallet. +func (w *Wallet) pair(puk []byte) error { + if w.session.paired() { + return fmt.Errorf("Wallet already paired") + } + pairing, err := w.session.pair(puk) + if err != nil { + return err + } + if err = w.Hub.setPairing(w, &pairing); err != nil { + return err + } + return w.session.authenticate(pairing) +} + +// Unpair deletes an existing wallet pairing. +func (w *Wallet) Unpair(pin []byte) error { + w.lock.Lock() + defer w.lock.Unlock() + + if !w.session.paired() { + return fmt.Errorf("wallet %x not paired", w.PublicKey) + } + if err := w.session.verifyPin(pin); err != nil { + return fmt.Errorf("failed to verify pin: %s", err) + } + if err := w.session.unpair(); err != nil { + return fmt.Errorf("failed to unpair: %s", err) + } + if err := w.Hub.setPairing(w, nil); err != nil { + return err + } + return nil +} + +// URL retrieves the canonical path under which this wallet is reachable. It is +// user by upper layers to define a sorting order over all wallets from multiple +// backends. +func (w *Wallet) URL() accounts.URL { + return accounts.URL{ + Scheme: w.Hub.scheme, + Path: fmt.Sprintf("%x", w.PublicKey[1:5]), // Byte #0 isn't unique; 1:5 covers << 64K cards, bump to 1:9 for << 4M + } +} + +// Status returns a textual status to aid the user in the current state of the +// wallet. It also returns an error indicating any failure the wallet might have +// encountered. +func (w *Wallet) Status() (string, error) { + w.lock.Lock() + defer w.lock.Unlock() + + // If the card is not paired, we can only wait + if !w.session.paired() { + return "Unpaired, waiting for pairing password", nil + } + // Yay, we have an encrypted session, retrieve the actual status + status, err := w.session.walletStatus() + if err != nil { + return fmt.Sprintf("Failed: %v", err), err + } + switch { + case !w.session.verified && status.PinRetryCount == 0 && status.PukRetryCount == 0: + return fmt.Sprintf("Bricked, waiting for full wipe"), nil + case !w.session.verified && status.PinRetryCount == 0: + return fmt.Sprintf("Blocked, waiting for PUK (%d attempts left) and new PIN", status.PukRetryCount), nil + case !w.session.verified: + return fmt.Sprintf("Locked, waiting for PIN (%d attempts left)", status.PinRetryCount), nil + case !status.Initialized: + return fmt.Sprintf("Empty, waiting for initialization"), nil + default: + return fmt.Sprintf("Online"), nil + } +} + +// Open initializes access to a wallet instance. It is not meant to unlock or +// decrypt account keys, rather simply to establish a connection to hardware +// wallets and/or to access derivation seeds. +// +// The passphrase parameter may or may not be used by the implementation of a +// particular wallet instance. The reason there is no passwordless open method +// is to strive towards a uniform wallet handling, oblivious to the different +// backend providers. +// +// Please note, if you open a wallet, you must close it to release any allocated +// resources (especially important when working with hardware wallets). +func (w *Wallet) Open(passphrase string) error { + w.lock.Lock() + defer w.lock.Unlock() + + // If the session is already open, bail out + if w.session.verified { + return ErrAlreadyOpen + } + // If the smart card is not yet paired, attempt to do so either from a previous + // pairing key or form the supplied PUK code. + if !w.session.paired() { + // If a previous pairing exists, only ever try to use that + if pairing := w.Hub.pairing(w); pairing != nil { + if err := w.session.authenticate(*pairing); err != nil { + return fmt.Errorf("failed to authenticate card %x: %s", w.PublicKey[:4], err) + } + // Pairing still ok, fall through to PIN checks + } else { + // If no passphrase was supplied, request the PUK from the user + if passphrase == "" { + return ErrPairingPasswordNeeded + } + // Attempt to pair the smart card with the user supplied PUK + if err := w.pair([]byte(passphrase)); err != nil { + return err + } + // Pairing succeeded, fall through to PIN checks. This will of course fail, + // but we can't return ErrPINNeeded directly here becase we don't know whether + // a PIN check or a PIN reset is needed. + passphrase = "" + } + } + // The smart card was successfully paired, retrieve its status to check whether + // PIN verification or unblocking is needed. + status, err := w.session.walletStatus() + if err != nil { + return err + } + // Request the appropriate next authentication data, or use the one supplied + switch { + case passphrase == "" && status.PinRetryCount > 0: + return ErrPINNeeded + case passphrase == "": + return ErrPINUnblockNeeded + case status.PinRetryCount > 0: + if !regexp.MustCompile(`^[0-9]{6,}$`).MatchString(passphrase) { + w.log.Error("PIN needs to be at least 6 digits") + return ErrPINNeeded + } + if err := w.session.verifyPin([]byte(passphrase)); err != nil { + return err + } + default: + if !regexp.MustCompile(`^[0-9]{12,}$`).MatchString(passphrase) { + w.log.Error("PUK needs to be at least 12 digits") + return ErrPINUnblockNeeded + } + if err := w.session.unblockPin([]byte(passphrase)); err != nil { + return err + } + } + // Smart card paired and unlocked, initialize and register + w.deriveReq = make(chan chan struct{}) + w.deriveQuit = make(chan chan error) + + go w.selfDerive() + + // Notify anyone listening for wallet events that a new device is accessible + go w.Hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened}) + + return nil +} + +// Close stops and closes the wallet, freeing any resources. +func (w *Wallet) Close() error { + // Ensure the wallet was opened + w.lock.Lock() + dQuit := w.deriveQuit + w.lock.Unlock() + + // Terminate the self-derivations + var derr error + if dQuit != nil { + errc := make(chan error) + dQuit <- errc + derr = <-errc // Save for later, we *must* close the USB + } + // Terminate the device connection + w.lock.Lock() + defer w.lock.Unlock() + + w.deriveQuit = nil + w.deriveReq = nil + + if err := w.release(); err != nil { + return err + } + return derr +} + +// selfDerive is an account derivation loop that upon request attempts to find +// new non-zero accounts. +func (w *Wallet) selfDerive() { + w.log.Debug("Smart card wallet self-derivation started") + defer w.log.Debug("Smart card wallet self-derivation stopped") + + // Execute self-derivations until termination or error + var ( + reqc chan struct{} + errc chan error + err error + ) + for errc == nil && err == nil { + // Wait until either derivation or termination is requested + select { + case errc = <-w.deriveQuit: + // Termination requested + continue + case reqc = <-w.deriveReq: + // Account discovery requested + } + // Derivation needs a chain and device access, skip if either unavailable + w.lock.Lock() + if w.session == nil || w.deriveChain == nil { + w.lock.Unlock() + reqc <- struct{}{} + continue + } + pairing := w.Hub.pairing(w) + + // Device lock obtained, derive the next batch of accounts + var ( + paths []accounts.DerivationPath + nextAcc accounts.Account + + nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...) + nextAddrs = append([]common.Address{}, w.deriveNextAddrs...) + + context = context.Background() + ) + for i := 0; i < len(nextAddrs); i++ { + for empty := false; !empty; { + // Retrieve the next derived Ethereum account + if nextAddrs[i] == (common.Address{}) { + if nextAcc, err = w.session.derive(nextPaths[i]); err != nil { + w.log.Warn("Smartcard wallet account derivation failed", "err", err) + break + } + nextAddrs[i] = nextAcc.Address + } + // Check the account's status against the current chain state + var ( + balance *big.Int + nonce uint64 + ) + balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil) + if err != nil { + w.log.Warn("Smartcard wallet balance retrieval failed", "err", err) + break + } + nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil) + if err != nil { + w.log.Warn("Smartcard wallet nonce retrieval failed", "err", err) + break + } + // If the next account is empty, stop self-derivation, but add for the last base path + if balance.Sign() == 0 && nonce == 0 { + empty = true + if i < len(nextAddrs)-1 { + break + } + } + // We've just self-derived a new account, start tracking it locally + path := make(accounts.DerivationPath, len(nextPaths[i])) + copy(path[:], nextPaths[i][:]) + paths = append(paths, path) + + // Display a log message to the user for new (or previously empty accounts) + if _, known := pairing.Accounts[nextAddrs[i]]; !known || !empty || nextAddrs[i] != w.deriveNextAddrs[i] { + w.log.Info("Smartcard wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce) + } + pairing.Accounts[nextAddrs[i]] = path + + // Fetch the next potential account + if !empty { + nextAddrs[i] = common.Address{} + nextPaths[i][len(nextPaths[i])-1]++ + } + } + } + // If there are new accounts, write them out + if len(paths) > 0 { + err = w.Hub.setPairing(w, pairing) + } + // Shift the self-derivation forward + w.deriveNextAddrs = nextAddrs + w.deriveNextPaths = nextPaths + + // Self derivation complete, release device lock + w.lock.Unlock() + + // Notify the user of termination and loop after a bit of time (to avoid trashing) + reqc <- struct{}{} + if err == nil { + select { + case errc = <-w.deriveQuit: + // Termination requested, abort + case <-time.After(selfDeriveThrottling): + // Waited enough, willing to self-derive again + } + } + } + // In case of error, wait for termination + if err != nil { + w.log.Debug("Smartcard wallet self-derivation failed", "err", err) + errc = <-w.deriveQuit + } + errc <- err +} + +// Accounts retrieves the list of signing accounts the wallet is currently aware +// of. For hierarchical deterministic wallets, the list will not be exhaustive, +// rather only contain the accounts explicitly pinned during account derivation. +func (w *Wallet) Accounts() []accounts.Account { + // Attempt self-derivation if it's running + reqc := make(chan struct{}, 1) + select { + case w.deriveReq <- reqc: + // Self-derivation request accepted, wait for it + <-reqc + default: + // Self-derivation offline, throttled or busy, skip + } + + w.lock.Lock() + defer w.lock.Unlock() + + if pairing := w.Hub.pairing(w); pairing != nil { + ret := make([]accounts.Account, 0, len(pairing.Accounts)) + for address, path := range pairing.Accounts { + ret = append(ret, w.makeAccount(address, path)) + } + sort.Sort(accounts.AccountsByURL(ret)) + return ret + } + return nil +} + +func (w *Wallet) makeAccount(address common.Address, path accounts.DerivationPath) accounts.Account { + return accounts.Account{ + Address: address, + URL: accounts.URL{ + Scheme: w.Hub.scheme, + Path: fmt.Sprintf("%x/%s", w.PublicKey[1:3], path.String()), + }, + } +} + +// Contains returns whether an account is part of this particular wallet or not. +func (w *Wallet) Contains(account accounts.Account) bool { + if pairing := w.Hub.pairing(w); pairing != nil { + _, ok := pairing.Accounts[account.Address] + return ok + } + return false +} + +// Initialize installs a keypair generated from the provided key into the wallet. +func (w *Wallet) Initialize(seed []byte) error { + go w.selfDerive() + // DO NOT lock at this stage, as the initialize + // function relies on Status() + return w.session.initialize(seed) +} + +// Derive attempts to explicitly derive a hierarchical deterministic account at +// the specified derivation path. If requested, the derived account will be added +// to the wallet's tracked account list. +func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + w.lock.Lock() + defer w.lock.Unlock() + + account, err := w.session.derive(path) + if err != nil { + return accounts.Account{}, err + } + + if pin { + pairing := w.Hub.pairing(w) + pairing.Accounts[account.Address] = path + if err := w.Hub.setPairing(w, pairing); err != nil { + return accounts.Account{}, err + } + } + + return account, nil +} + +// SelfDerive sets a base account derivation path from which the wallet attempts +// to discover non zero accounts and automatically add them to list of tracked +// accounts. +// +// Note, self derivaton will increment the last component of the specified path +// opposed to decending into a child path to allow discovering accounts starting +// from non zero components. +// +// Some hardware wallets switched derivation paths through their evolution, so +// this method supports providing multiple bases to discover old user accounts +// too. Only the last base will be used to derive the next empty account. +// +// You can disable automatic account discovery by calling SelfDerive with a nil +// chain state reader. +func (w *Wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { + w.lock.Lock() + defer w.lock.Unlock() + + w.deriveNextPaths = make([]accounts.DerivationPath, len(bases)) + for i, base := range bases { + w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base)) + copy(w.deriveNextPaths[i][:], base[:]) + } + w.deriveNextAddrs = make([]common.Address, len(bases)) + w.deriveChain = chain +} + +// SignData requests the wallet to sign the hash of the given data. +// +// It looks up the account specified either solely via its address contained within, +// or optionally with the aid of any location metadata from the embedded URL field. +// +// If the wallet requires additional authentication to sign the request (e.g. +// a password to decrypt the account, or a PIN code o verify the transaction), +// an AuthNeededError instance will be returned, containing infos for the user +// about which fields or actions are needed. The user may retry by providing +// the needed details via SignDataWithPassphrase, or by other means (e.g. unlock +// the account in a keystore). +func (w *Wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + return w.signHash(account, crypto.Keccak256(data)) +} + +func (w *Wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { + w.lock.Lock() + defer w.lock.Unlock() + + path, err := w.findAccountPath(account) + if err != nil { + return nil, err + } + + return w.session.sign(path, hash) +} + +// SignTx requests the wallet to sign the given transaction. +// +// It looks up the account specified either solely via its address contained within, +// or optionally with the aid of any location metadata from the embedded URL field. +// +// If the wallet requires additional authentication to sign the request (e.g. +// a password to decrypt the account, or a PIN code o verify the transaction), +// an AuthNeededError instance will be returned, containing infos for the user +// about which fields or actions are needed. The user may retry by providing +// the needed details via SignTxWithPassphrase, or by other means (e.g. unlock +// the account in a keystore). +func (w *Wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + signer := types.NewEIP155Signer(chainID) + hash := signer.Hash(tx) + sig, err := w.signHash(account, hash[:]) + if err != nil { + return nil, err + } + return tx.WithSignature(signer, sig) +} + +// SignDataWithPassphrase requests the wallet to sign the given hash with the +// given passphrase as extra authentication information. +// +// It looks up the account specified either solely via its address contained within, +// or optionally with the aid of any location metadata from the embedded URL field. +func (w *Wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return w.signHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) +} + +func (w *Wallet) signHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { + if !w.session.verified { + if err := w.Open(passphrase); err != nil { + return nil, err + } + } + + return w.signHash(account, hash) +} + +// SignText requests the wallet to sign the hash of a given piece of data, prefixed +// by the Ethereum prefix scheme +// It looks up the account specified either solely via its address contained within, +// or optionally with the aid of any location metadata from the embedded URL field. +// +// If the wallet requires additional authentication to sign the request (e.g. +// a password to decrypt the account, or a PIN code o verify the transaction), +// an AuthNeededError instance will be returned, containing infos for the user +// about which fields or actions are needed. The user may retry by providing +// the needed details via SignHashWithPassphrase, or by other means (e.g. unlock +// the account in a keystore). +func (w *Wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + return w.signHash(account, accounts.TextHash(text)) +} + +// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the +// given hash with the given account using passphrase as extra authentication +func (w *Wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return w.signHashWithPassphrase(account, passphrase, crypto.Keccak256(accounts.TextHash(text))) +} + +// SignTxWithPassphrase requests the wallet to sign the given transaction, with the +// given passphrase as extra authentication information. +// +// It looks up the account specified either solely via its address contained within, +// or optionally with the aid of any location metadata from the embedded URL field. +func (w *Wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + if !w.session.verified { + if err := w.Open(passphrase); err != nil { + return nil, err + } + } + return w.SignTx(account, tx, chainID) +} + +// findAccountPath returns the derivation path for the provided account. +// It first checks for the address in the list of pinned accounts, and if it is +// not found, attempts to parse the derivation path from the account's URL. +func (w *Wallet) findAccountPath(account accounts.Account) (accounts.DerivationPath, error) { + pairing := w.Hub.pairing(w) + if path, ok := pairing.Accounts[account.Address]; ok { + return path, nil + } + + // Look for the path in the URL + if account.URL.Scheme != w.Hub.scheme { + return nil, fmt.Errorf("Scheme %s does not match wallet scheme %s", account.URL.Scheme, w.Hub.scheme) + } + + parts := strings.SplitN(account.URL.Path, "/", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("Invalid URL format: %s", account.URL) + } + + if parts[0] != fmt.Sprintf("%x", w.PublicKey[1:3]) { + return nil, fmt.Errorf("URL %s is not for this wallet", account.URL) + } + + return accounts.ParseDerivationPath(parts[1]) +} + +// Session represents a secured communication session with the wallet. +type Session struct { + Wallet *Wallet // A handle to the wallet that opened the session + Channel *SecureChannelSession // A secure channel for encrypted messages + verified bool // Whether the pin has been verified in this session. +} + +// pair establishes a new pairing over this channel, using the provided secret. +func (s *Session) pair(secret []byte) (smartcardPairing, error) { + err := s.Channel.Pair(secret) + if err != nil { + return smartcardPairing{}, err + } + + return smartcardPairing{ + PublicKey: s.Wallet.PublicKey, + PairingIndex: s.Channel.PairingIndex, + PairingKey: s.Channel.PairingKey, + Accounts: make(map[common.Address]accounts.DerivationPath), + }, nil +} + +// unpair deletes an existing pairing. +func (s *Session) unpair() error { + if !s.verified { + return fmt.Errorf("Unpair requires that the PIN be verified") + } + return s.Channel.Unpair() +} + +// verifyPin unlocks a wallet with the provided pin. +func (s *Session) verifyPin(pin []byte) error { + if _, err := s.Channel.transmitEncrypted(claSCWallet, insVerifyPin, 0, 0, pin); err != nil { + return err + } + s.verified = true + return nil +} + +// unblockPin unblocks a wallet with the provided puk and resets the pin to the +// new one specified. +func (s *Session) unblockPin(pukpin []byte) error { + if _, err := s.Channel.transmitEncrypted(claSCWallet, insUnblockPin, 0, 0, pukpin); err != nil { + return err + } + s.verified = true + return nil +} + +// release releases resources associated with the channel. +func (s *Session) release() error { + return s.Wallet.card.Disconnect(pcsc.LeaveCard) +} + +// paired returns true if a valid pairing exists. +func (s *Session) paired() bool { + return s.Channel.PairingKey != nil +} + +// authenticate uses an existing pairing to establish a secure channel. +func (s *Session) authenticate(pairing smartcardPairing) error { + if !bytes.Equal(s.Wallet.PublicKey, pairing.PublicKey) { + return fmt.Errorf("Cannot pair using another wallet's pairing; %x != %x", s.Wallet.PublicKey, pairing.PublicKey) + } + s.Channel.PairingKey = pairing.PairingKey + s.Channel.PairingIndex = pairing.PairingIndex + return s.Channel.Open() +} + +// walletStatus describes a smartcard wallet's status information. +type walletStatus struct { + PinRetryCount int // Number of remaining PIN retries + PukRetryCount int // Number of remaining PUK retries + Initialized bool // Whether the card has been initialized with a private key +} + +// walletStatus fetches the wallet's status from the card. +func (s *Session) walletStatus() (*walletStatus, error) { + response, err := s.Channel.transmitEncrypted(claSCWallet, insStatus, statusP1WalletStatus, 0, nil) + if err != nil { + return nil, err + } + + status := new(walletStatus) + if _, err := asn1.UnmarshalWithParams(response.Data, status, "tag:3"); err != nil { + return nil, err + } + return status, nil +} + +// derivationPath fetches the wallet's current derivation path from the card. +func (s *Session) derivationPath() (accounts.DerivationPath, error) { + response, err := s.Channel.transmitEncrypted(claSCWallet, insStatus, statusP1Path, 0, nil) + if err != nil { + return nil, err + } + buf := bytes.NewReader(response.Data) + path := make(accounts.DerivationPath, len(response.Data)/4) + return path, binary.Read(buf, binary.BigEndian, &path) +} + +// initializeData contains data needed to initialize the smartcard wallet. +type initializeData struct { + PublicKey []byte `asn1:"tag:0"` + PrivateKey []byte `asn1:"tag:1"` + ChainCode []byte `asn1:"tag:2"` +} + +// initialize initializes the card with new key data. +func (s *Session) initialize(seed []byte) error { + // Check that the wallet isn't currently initialized, + // otherwise the key would be overwritten. + status, err := s.Wallet.Status() + if err != nil { + return err + } + if status == "Online" { + return fmt.Errorf("card is already initialized, cowardly refusing to proceed") + } + + s.Wallet.lock.Lock() + defer s.Wallet.lock.Unlock() + + // HMAC the seed to produce the private key and chain code + mac := hmac.New(sha512.New, []byte("Bitcoin seed")) + mac.Write(seed) + seed = mac.Sum(nil) + + key, err := crypto.ToECDSA(seed[:32]) + if err != nil { + return err + } + + id := initializeData{} + id.PublicKey = crypto.FromECDSAPub(&key.PublicKey) + id.PrivateKey = seed[:32] + id.ChainCode = seed[32:] + data, err := asn1.Marshal(id) + if err != nil { + return err + } + + // Nasty hack to force the top-level struct tag to be context-specific + data[0] = 0xA1 + + _, err = s.Channel.transmitEncrypted(claSCWallet, insLoadKey, 0x02, 0, data) + return err +} + +// derive derives a new HD key path on the card. +func (s *Session) derive(path accounts.DerivationPath) (accounts.Account, error) { + startingPoint, path, err := derivationpath.Decode(path.String()) + if err != nil { + return accounts.Account{}, err + } + + var p1 uint8 + switch startingPoint { + case derivationpath.StartingPointMaster: + p1 = P1DeriveKeyFromMaster + case derivationpath.StartingPointParent: + p1 = P1DeriveKeyFromParent + case derivationpath.StartingPointCurrent: + p1 = P1DeriveKeyFromCurrent + default: + return accounts.Account{}, fmt.Errorf("invalid startingPoint %d", startingPoint) + } + + data := new(bytes.Buffer) + for _, segment := range path { + if err := binary.Write(data, binary.BigEndian, segment); err != nil { + return accounts.Account{}, err + } + } + + _, err = s.Channel.transmitEncrypted(claSCWallet, insDeriveKey, p1, 0, data.Bytes()) + if err != nil { + return accounts.Account{}, err + } + + response, err := s.Channel.transmitEncrypted(claSCWallet, insSign, 0, 0, DerivationSignatureHash[:]) + if err != nil { + return accounts.Account{}, err + } + + sigdata := new(signatureData) + if _, err := asn1.UnmarshalWithParams(response.Data, sigdata, "tag:0"); err != nil { + return accounts.Account{}, err + } + rbytes, sbytes := sigdata.Signature.R.Bytes(), sigdata.Signature.S.Bytes() + sig := make([]byte, 65) + copy(sig[32-len(rbytes):32], rbytes) + copy(sig[64-len(sbytes):64], sbytes) + + if err := confirmPublicKey(sig, sigdata.PublicKey); err != nil { + return accounts.Account{}, err + } + pub, err := crypto.UnmarshalPubkey(sigdata.PublicKey) + if err != nil { + return accounts.Account{}, err + } + return s.Wallet.makeAccount(crypto.PubkeyToAddress(*pub), path), nil +} + +// keyExport contains information on an exported keypair. +type keyExport struct { + PublicKey []byte `asn1:"tag:0"` + PrivateKey []byte `asn1:"tag:1,optional"` +} + +// publicKey returns the public key for the current derivation path. +func (s *Session) publicKey() ([]byte, error) { + response, err := s.Channel.transmitEncrypted(claSCWallet, insExportKey, exportP1Any, exportP2Pubkey, nil) + if err != nil { + return nil, err + } + keys := new(keyExport) + if _, err := asn1.UnmarshalWithParams(response.Data, keys, "tag:1"); err != nil { + return nil, err + } + return keys.PublicKey, nil +} + +// signatureData contains information on a signature - the signature itself and +// the corresponding public key. +type signatureData struct { + PublicKey []byte `asn1:"tag:0"` + Signature struct { + R *big.Int + S *big.Int + } +} + +// sign asks the card to sign a message, and returns a valid signature after +// recovering the v value. +func (s *Session) sign(path accounts.DerivationPath, hash []byte) ([]byte, error) { + startTime := time.Now() + _, err := s.derive(path) + if err != nil { + return nil, err + } + deriveTime := time.Now() + + response, err := s.Channel.transmitEncrypted(claSCWallet, insSign, signP1PrecomputedHash, signP2OnlyBlock, hash) + if err != nil { + return nil, err + } + sigdata := new(signatureData) + if _, err := asn1.UnmarshalWithParams(response.Data, sigdata, "tag:0"); err != nil { + return nil, err + } + // Serialize the signature + rbytes, sbytes := sigdata.Signature.R.Bytes(), sigdata.Signature.S.Bytes() + sig := make([]byte, 65) + copy(sig[32-len(rbytes):32], rbytes) + copy(sig[64-len(sbytes):64], sbytes) + + // Recover the V value. + sig, err = makeRecoverableSignature(hash, sig, sigdata.PublicKey) + if err != nil { + return nil, err + } + log.Debug("Signed using smartcard", "deriveTime", deriveTime.Sub(startTime), "signingTime", time.Since(deriveTime)) + + return sig, nil +} + +// confirmPublicKey confirms that the given signature belongs to the specified key. +func confirmPublicKey(sig, pubkey []byte) error { + _, err := makeRecoverableSignature(DerivationSignatureHash[:], sig, pubkey) + return err +} + +// makeRecoverableSignature uses a signature and an expected public key to +// recover the v value and produce a recoverable signature. +func makeRecoverableSignature(hash, sig, expectedPubkey []byte) ([]byte, error) { + var libraryError error + for v := 0; v < 2; v++ { + sig[64] = byte(v) + if pubkey, err := crypto.Ecrecover(hash, sig); err == nil { + if bytes.Equal(pubkey, expectedPubkey) { + return sig, nil + } + } else { + libraryError = err + } + } + if libraryError != nil { + return nil, libraryError + } + return nil, ErrPubkeyMismatch +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/sort.go b/vendor/github.com/ethereum/go-ethereum/accounts/sort.go new file mode 100644 index 000000000..f46762114 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/sort.go @@ -0,0 +1,31 @@ +// 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 accounts + +// AccountsByURL implements sort.Interface for []Account based on the URL field. +type AccountsByURL []Account + +func (a AccountsByURL) Len() int { return len(a) } +func (a AccountsByURL) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a AccountsByURL) Less(i, j int) bool { return a[i].URL.Cmp(a[j].URL) < 0 } + +// WalletsByURL implements sort.Interface for []Wallet based on the URL field. +type WalletsByURL []Wallet + +func (w WalletsByURL) Len() int { return len(w) } +func (w WalletsByURL) Swap(i, j int) { w[i], w[j] = w[j], w[i] } +func (w WalletsByURL) Less(i, j int) bool { return w[i].URL().Cmp(w[j].URL()) < 0 } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go index 640320bc9..23be98a08 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/hub.go @@ -20,12 +20,13 @@ import ( "errors" "runtime" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - "github.com/karalabe/hid" + "github.com/karalabe/usb" ) // LedgerScheme is the protocol scheme prefixing account and wallet URLs. @@ -64,21 +65,41 @@ type Hub struct { // TODO(karalabe): remove if hotplug lands on Windows commsPend int // Number of operations blocking enumeration commsLock sync.Mutex // Lock protecting the pending counter and enumeration + enumFails uint32 // Number of times enumeration has failed } // NewLedgerHub creates a new hardware wallet manager for Ledger devices. func NewLedgerHub() (*Hub, error) { - return newHub(LedgerScheme, 0x2c97, []uint16{0x0000 /* Ledger Blue */, 0x0001 /* Ledger Nano S */}, 0xffa0, 0, newLedgerDriver) + return newHub(LedgerScheme, 0x2c97, []uint16{ + // Original product IDs + 0x0000, /* Ledger Blue */ + 0x0001, /* Ledger Nano S */ + 0x0004, /* Ledger Nano X */ + + // Upcoming product IDs: https://www.ledger.com/2019/05/17/windows-10-update-sunsetting-u2f-tunnel-transport-for-ledger-devices/ + 0x0015, /* HID + U2F + WebUSB Ledger Blue */ + 0x1015, /* HID + U2F + WebUSB Ledger Nano S */ + 0x4015, /* HID + U2F + WebUSB Ledger Nano X */ + 0x0011, /* HID + WebUSB Ledger Blue */ + 0x1011, /* HID + WebUSB Ledger Nano S */ + 0x4011, /* HID + WebUSB Ledger Nano X */ + }, 0xffa0, 0, newLedgerDriver) } -// NewTrezorHub creates a new hardware wallet manager for Trezor devices. -func NewTrezorHub() (*Hub, error) { - return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor 1 */}, 0xff00, 0, newTrezorDriver) +// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices. +func NewTrezorHubWithHID() (*Hub, error) { + return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver) +} + +// NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with +// firmware version > 1.8.0 +func NewTrezorHubWithWebUSB() (*Hub, error) { + return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver) } // newHub creates a new hardware wallet manager for generic USB devices. func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) { - if !hid.Supported() { + if !usb.Supported() { return nil, errors.New("unsupported platform") } hub := &Hub{ @@ -119,8 +140,12 @@ func (hub *Hub) refreshWallets() { if elapsed < refreshThrottling { return } + // If USB enumeration is continually failing, don't keep trying indefinitely + if atomic.LoadUint32(&hub.enumFails) > 2 { + return + } // Retrieve the current list of USB wallet devices - var devices []hid.DeviceInfo + var devices []usb.DeviceInfo if runtime.GOOS == "linux" { // hidapi on Linux opens the device during enumeration to retrieve some infos, @@ -135,8 +160,22 @@ func (hub *Hub) refreshWallets() { return } } - for _, info := range hid.Enumerate(hub.vendorID, 0) { + infos, err := usb.Enumerate(hub.vendorID, 0) + if err != nil { + failcount := atomic.AddUint32(&hub.enumFails, 1) + if runtime.GOOS == "linux" { + // See rationale before the enumeration why this is needed and only on Linux. + hub.commsLock.Unlock() + } + log.Error("Failed to enumerate USB devices", "hub", hub.scheme, + "vendor", hub.vendorID, "failcount", failcount, "err", err) + return + } + atomic.StoreUint32(&hub.enumFails, 0) + + for _, info := range infos { for _, id := range hub.productIDs { + // Windows and Macos use UsageID matching, Linux uses Interface matching if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { devices = append(devices, info) break @@ -150,8 +189,10 @@ func (hub *Hub) refreshWallets() { // Transform the current list of wallets into the new one hub.stateLock.Lock() - wallets := make([]accounts.Wallet, 0, len(devices)) - events := []accounts.WalletEvent{} + var ( + wallets = make([]accounts.Wallet, 0, len(devices)) + events []accounts.WalletEvent + ) for _, device := range devices { url := accounts.URL{Scheme: hub.scheme, Path: device.Path} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.pb.go deleted file mode 100644 index 15bb6fb73..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.pb.go +++ /dev/null @@ -1,3081 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: messages.proto - -package trezor - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// * -// Mapping between Trezor wire identifier (uint) and a protobuf message -type MessageType int32 - -const ( - MessageType_MessageType_Initialize MessageType = 0 - MessageType_MessageType_Ping MessageType = 1 - MessageType_MessageType_Success MessageType = 2 - MessageType_MessageType_Failure MessageType = 3 - MessageType_MessageType_ChangePin MessageType = 4 - MessageType_MessageType_WipeDevice MessageType = 5 - MessageType_MessageType_FirmwareErase MessageType = 6 - MessageType_MessageType_FirmwareUpload MessageType = 7 - MessageType_MessageType_FirmwareRequest MessageType = 8 - MessageType_MessageType_GetEntropy MessageType = 9 - MessageType_MessageType_Entropy MessageType = 10 - MessageType_MessageType_GetPublicKey MessageType = 11 - MessageType_MessageType_PublicKey MessageType = 12 - MessageType_MessageType_LoadDevice MessageType = 13 - MessageType_MessageType_ResetDevice MessageType = 14 - MessageType_MessageType_SignTx MessageType = 15 - MessageType_MessageType_SimpleSignTx MessageType = 16 - MessageType_MessageType_Features MessageType = 17 - MessageType_MessageType_PinMatrixRequest MessageType = 18 - MessageType_MessageType_PinMatrixAck MessageType = 19 - MessageType_MessageType_Cancel MessageType = 20 - MessageType_MessageType_TxRequest MessageType = 21 - MessageType_MessageType_TxAck MessageType = 22 - MessageType_MessageType_CipherKeyValue MessageType = 23 - MessageType_MessageType_ClearSession MessageType = 24 - MessageType_MessageType_ApplySettings MessageType = 25 - MessageType_MessageType_ButtonRequest MessageType = 26 - MessageType_MessageType_ButtonAck MessageType = 27 - MessageType_MessageType_ApplyFlags MessageType = 28 - MessageType_MessageType_GetAddress MessageType = 29 - MessageType_MessageType_Address MessageType = 30 - MessageType_MessageType_SelfTest MessageType = 32 - MessageType_MessageType_BackupDevice MessageType = 34 - MessageType_MessageType_EntropyRequest MessageType = 35 - MessageType_MessageType_EntropyAck MessageType = 36 - MessageType_MessageType_SignMessage MessageType = 38 - MessageType_MessageType_VerifyMessage MessageType = 39 - MessageType_MessageType_MessageSignature MessageType = 40 - MessageType_MessageType_PassphraseRequest MessageType = 41 - MessageType_MessageType_PassphraseAck MessageType = 42 - MessageType_MessageType_EstimateTxSize MessageType = 43 - MessageType_MessageType_TxSize MessageType = 44 - MessageType_MessageType_RecoveryDevice MessageType = 45 - MessageType_MessageType_WordRequest MessageType = 46 - MessageType_MessageType_WordAck MessageType = 47 - MessageType_MessageType_CipheredKeyValue MessageType = 48 - MessageType_MessageType_EncryptMessage MessageType = 49 - MessageType_MessageType_EncryptedMessage MessageType = 50 - MessageType_MessageType_DecryptMessage MessageType = 51 - MessageType_MessageType_DecryptedMessage MessageType = 52 - MessageType_MessageType_SignIdentity MessageType = 53 - MessageType_MessageType_SignedIdentity MessageType = 54 - MessageType_MessageType_GetFeatures MessageType = 55 - MessageType_MessageType_EthereumGetAddress MessageType = 56 - MessageType_MessageType_EthereumAddress MessageType = 57 - MessageType_MessageType_EthereumSignTx MessageType = 58 - MessageType_MessageType_EthereumTxRequest MessageType = 59 - MessageType_MessageType_EthereumTxAck MessageType = 60 - MessageType_MessageType_GetECDHSessionKey MessageType = 61 - MessageType_MessageType_ECDHSessionKey MessageType = 62 - MessageType_MessageType_SetU2FCounter MessageType = 63 - MessageType_MessageType_EthereumSignMessage MessageType = 64 - MessageType_MessageType_EthereumVerifyMessage MessageType = 65 - MessageType_MessageType_EthereumMessageSignature MessageType = 66 - MessageType_MessageType_DebugLinkDecision MessageType = 100 - MessageType_MessageType_DebugLinkGetState MessageType = 101 - MessageType_MessageType_DebugLinkState MessageType = 102 - MessageType_MessageType_DebugLinkStop MessageType = 103 - MessageType_MessageType_DebugLinkLog MessageType = 104 - MessageType_MessageType_DebugLinkMemoryRead MessageType = 110 - MessageType_MessageType_DebugLinkMemory MessageType = 111 - MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112 - MessageType_MessageType_DebugLinkFlashErase MessageType = 113 -) - -var MessageType_name = map[int32]string{ - 0: "MessageType_Initialize", - 1: "MessageType_Ping", - 2: "MessageType_Success", - 3: "MessageType_Failure", - 4: "MessageType_ChangePin", - 5: "MessageType_WipeDevice", - 6: "MessageType_FirmwareErase", - 7: "MessageType_FirmwareUpload", - 8: "MessageType_FirmwareRequest", - 9: "MessageType_GetEntropy", - 10: "MessageType_Entropy", - 11: "MessageType_GetPublicKey", - 12: "MessageType_PublicKey", - 13: "MessageType_LoadDevice", - 14: "MessageType_ResetDevice", - 15: "MessageType_SignTx", - 16: "MessageType_SimpleSignTx", - 17: "MessageType_Features", - 18: "MessageType_PinMatrixRequest", - 19: "MessageType_PinMatrixAck", - 20: "MessageType_Cancel", - 21: "MessageType_TxRequest", - 22: "MessageType_TxAck", - 23: "MessageType_CipherKeyValue", - 24: "MessageType_ClearSession", - 25: "MessageType_ApplySettings", - 26: "MessageType_ButtonRequest", - 27: "MessageType_ButtonAck", - 28: "MessageType_ApplyFlags", - 29: "MessageType_GetAddress", - 30: "MessageType_Address", - 32: "MessageType_SelfTest", - 34: "MessageType_BackupDevice", - 35: "MessageType_EntropyRequest", - 36: "MessageType_EntropyAck", - 38: "MessageType_SignMessage", - 39: "MessageType_VerifyMessage", - 40: "MessageType_MessageSignature", - 41: "MessageType_PassphraseRequest", - 42: "MessageType_PassphraseAck", - 43: "MessageType_EstimateTxSize", - 44: "MessageType_TxSize", - 45: "MessageType_RecoveryDevice", - 46: "MessageType_WordRequest", - 47: "MessageType_WordAck", - 48: "MessageType_CipheredKeyValue", - 49: "MessageType_EncryptMessage", - 50: "MessageType_EncryptedMessage", - 51: "MessageType_DecryptMessage", - 52: "MessageType_DecryptedMessage", - 53: "MessageType_SignIdentity", - 54: "MessageType_SignedIdentity", - 55: "MessageType_GetFeatures", - 56: "MessageType_EthereumGetAddress", - 57: "MessageType_EthereumAddress", - 58: "MessageType_EthereumSignTx", - 59: "MessageType_EthereumTxRequest", - 60: "MessageType_EthereumTxAck", - 61: "MessageType_GetECDHSessionKey", - 62: "MessageType_ECDHSessionKey", - 63: "MessageType_SetU2FCounter", - 64: "MessageType_EthereumSignMessage", - 65: "MessageType_EthereumVerifyMessage", - 66: "MessageType_EthereumMessageSignature", - 100: "MessageType_DebugLinkDecision", - 101: "MessageType_DebugLinkGetState", - 102: "MessageType_DebugLinkState", - 103: "MessageType_DebugLinkStop", - 104: "MessageType_DebugLinkLog", - 110: "MessageType_DebugLinkMemoryRead", - 111: "MessageType_DebugLinkMemory", - 112: "MessageType_DebugLinkMemoryWrite", - 113: "MessageType_DebugLinkFlashErase", -} -var MessageType_value = map[string]int32{ - "MessageType_Initialize": 0, - "MessageType_Ping": 1, - "MessageType_Success": 2, - "MessageType_Failure": 3, - "MessageType_ChangePin": 4, - "MessageType_WipeDevice": 5, - "MessageType_FirmwareErase": 6, - "MessageType_FirmwareUpload": 7, - "MessageType_FirmwareRequest": 8, - "MessageType_GetEntropy": 9, - "MessageType_Entropy": 10, - "MessageType_GetPublicKey": 11, - "MessageType_PublicKey": 12, - "MessageType_LoadDevice": 13, - "MessageType_ResetDevice": 14, - "MessageType_SignTx": 15, - "MessageType_SimpleSignTx": 16, - "MessageType_Features": 17, - "MessageType_PinMatrixRequest": 18, - "MessageType_PinMatrixAck": 19, - "MessageType_Cancel": 20, - "MessageType_TxRequest": 21, - "MessageType_TxAck": 22, - "MessageType_CipherKeyValue": 23, - "MessageType_ClearSession": 24, - "MessageType_ApplySettings": 25, - "MessageType_ButtonRequest": 26, - "MessageType_ButtonAck": 27, - "MessageType_ApplyFlags": 28, - "MessageType_GetAddress": 29, - "MessageType_Address": 30, - "MessageType_SelfTest": 32, - "MessageType_BackupDevice": 34, - "MessageType_EntropyRequest": 35, - "MessageType_EntropyAck": 36, - "MessageType_SignMessage": 38, - "MessageType_VerifyMessage": 39, - "MessageType_MessageSignature": 40, - "MessageType_PassphraseRequest": 41, - "MessageType_PassphraseAck": 42, - "MessageType_EstimateTxSize": 43, - "MessageType_TxSize": 44, - "MessageType_RecoveryDevice": 45, - "MessageType_WordRequest": 46, - "MessageType_WordAck": 47, - "MessageType_CipheredKeyValue": 48, - "MessageType_EncryptMessage": 49, - "MessageType_EncryptedMessage": 50, - "MessageType_DecryptMessage": 51, - "MessageType_DecryptedMessage": 52, - "MessageType_SignIdentity": 53, - "MessageType_SignedIdentity": 54, - "MessageType_GetFeatures": 55, - "MessageType_EthereumGetAddress": 56, - "MessageType_EthereumAddress": 57, - "MessageType_EthereumSignTx": 58, - "MessageType_EthereumTxRequest": 59, - "MessageType_EthereumTxAck": 60, - "MessageType_GetECDHSessionKey": 61, - "MessageType_ECDHSessionKey": 62, - "MessageType_SetU2FCounter": 63, - "MessageType_EthereumSignMessage": 64, - "MessageType_EthereumVerifyMessage": 65, - "MessageType_EthereumMessageSignature": 66, - "MessageType_DebugLinkDecision": 100, - "MessageType_DebugLinkGetState": 101, - "MessageType_DebugLinkState": 102, - "MessageType_DebugLinkStop": 103, - "MessageType_DebugLinkLog": 104, - "MessageType_DebugLinkMemoryRead": 110, - "MessageType_DebugLinkMemory": 111, - "MessageType_DebugLinkMemoryWrite": 112, - "MessageType_DebugLinkFlashErase": 113, -} - -func (x MessageType) Enum() *MessageType { - p := new(MessageType) - *p = x - return p -} -func (x MessageType) String() string { - return proto.EnumName(MessageType_name, int32(x)) -} -func (x *MessageType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType") - if err != nil { - return err - } - *x = MessageType(value) - return nil -} -func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } - -// * -// Request: Reset device to default state and ask for device details -// @next Features -type Initialize struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Initialize) Reset() { *m = Initialize{} } -func (m *Initialize) String() string { return proto.CompactTextString(m) } -func (*Initialize) ProtoMessage() {} -func (*Initialize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } - -// * -// Request: Ask for device details (no device reset) -// @next Features -type GetFeatures struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetFeatures) Reset() { *m = GetFeatures{} } -func (m *GetFeatures) String() string { return proto.CompactTextString(m) } -func (*GetFeatures) ProtoMessage() {} -func (*GetFeatures) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } - -// * -// Response: Reports various information about the device -// @prev Initialize -// @prev GetFeatures -type Features struct { - Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` - MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` - MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` - PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` - BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` - DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` - PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` - Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` - Coins []*CoinType `protobuf:"bytes,11,rep,name=coins" json:"coins,omitempty"` - Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` - Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` - BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` - Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` - PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` - PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` - FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` - NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` - Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Features) Reset() { *m = Features{} } -func (m *Features) String() string { return proto.CompactTextString(m) } -func (*Features) ProtoMessage() {} -func (*Features) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } - -func (m *Features) GetVendor() string { - if m != nil && m.Vendor != nil { - return *m.Vendor - } - return "" -} - -func (m *Features) GetMajorVersion() uint32 { - if m != nil && m.MajorVersion != nil { - return *m.MajorVersion - } - return 0 -} - -func (m *Features) GetMinorVersion() uint32 { - if m != nil && m.MinorVersion != nil { - return *m.MinorVersion - } - return 0 -} - -func (m *Features) GetPatchVersion() uint32 { - if m != nil && m.PatchVersion != nil { - return *m.PatchVersion - } - return 0 -} - -func (m *Features) GetBootloaderMode() bool { - if m != nil && m.BootloaderMode != nil { - return *m.BootloaderMode - } - return false -} - -func (m *Features) GetDeviceId() string { - if m != nil && m.DeviceId != nil { - return *m.DeviceId - } - return "" -} - -func (m *Features) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *Features) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *Features) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return "" -} - -func (m *Features) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *Features) GetCoins() []*CoinType { - if m != nil { - return m.Coins - } - return nil -} - -func (m *Features) GetInitialized() bool { - if m != nil && m.Initialized != nil { - return *m.Initialized - } - return false -} - -func (m *Features) GetRevision() []byte { - if m != nil { - return m.Revision - } - return nil -} - -func (m *Features) GetBootloaderHash() []byte { - if m != nil { - return m.BootloaderHash - } - return nil -} - -func (m *Features) GetImported() bool { - if m != nil && m.Imported != nil { - return *m.Imported - } - return false -} - -func (m *Features) GetPinCached() bool { - if m != nil && m.PinCached != nil { - return *m.PinCached - } - return false -} - -func (m *Features) GetPassphraseCached() bool { - if m != nil && m.PassphraseCached != nil { - return *m.PassphraseCached - } - return false -} - -func (m *Features) GetFirmwarePresent() bool { - if m != nil && m.FirmwarePresent != nil { - return *m.FirmwarePresent - } - return false -} - -func (m *Features) GetNeedsBackup() bool { - if m != nil && m.NeedsBackup != nil { - return *m.NeedsBackup - } - return false -} - -func (m *Features) GetFlags() uint32 { - if m != nil && m.Flags != nil { - return *m.Flags - } - return 0 -} - -// * -// Request: clear session (removes cached PIN, passphrase, etc). -// @next Success -type ClearSession struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *ClearSession) Reset() { *m = ClearSession{} } -func (m *ClearSession) String() string { return proto.CompactTextString(m) } -func (*ClearSession) ProtoMessage() {} -func (*ClearSession) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } - -// * -// Request: change language and/or label of the device -// @next Success -// @next Failure -// @next ButtonRequest -// @next PinMatrixRequest -type ApplySettings struct { - Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"` - Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"` - UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"` - Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ApplySettings) Reset() { *m = ApplySettings{} } -func (m *ApplySettings) String() string { return proto.CompactTextString(m) } -func (*ApplySettings) ProtoMessage() {} -func (*ApplySettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } - -func (m *ApplySettings) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return "" -} - -func (m *ApplySettings) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *ApplySettings) GetUsePassphrase() bool { - if m != nil && m.UsePassphrase != nil { - return *m.UsePassphrase - } - return false -} - -func (m *ApplySettings) GetHomescreen() []byte { - if m != nil { - return m.Homescreen - } - return nil -} - -// * -// Request: set flags of the device -// @next Success -// @next Failure -type ApplyFlags struct { - Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ApplyFlags) Reset() { *m = ApplyFlags{} } -func (m *ApplyFlags) String() string { return proto.CompactTextString(m) } -func (*ApplyFlags) ProtoMessage() {} -func (*ApplyFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } - -func (m *ApplyFlags) GetFlags() uint32 { - if m != nil && m.Flags != nil { - return *m.Flags - } - return 0 -} - -// * -// Request: Starts workflow for setting/changing/removing the PIN -// @next ButtonRequest -// @next PinMatrixRequest -type ChangePin struct { - Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ChangePin) Reset() { *m = ChangePin{} } -func (m *ChangePin) String() string { return proto.CompactTextString(m) } -func (*ChangePin) ProtoMessage() {} -func (*ChangePin) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } - -func (m *ChangePin) GetRemove() bool { - if m != nil && m.Remove != nil { - return *m.Remove - } - return false -} - -// * -// Request: Test if the device is alive, device sends back the message in Success response -// @next Success -type Ping struct { - Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` - ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` - PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Ping) Reset() { *m = Ping{} } -func (m *Ping) String() string { return proto.CompactTextString(m) } -func (*Ping) ProtoMessage() {} -func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } - -func (m *Ping) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -func (m *Ping) GetButtonProtection() bool { - if m != nil && m.ButtonProtection != nil { - return *m.ButtonProtection - } - return false -} - -func (m *Ping) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *Ping) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -// * -// Response: Success of the previous request -type Success struct { - Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Success) Reset() { *m = Success{} } -func (m *Success) String() string { return proto.CompactTextString(m) } -func (*Success) ProtoMessage() {} -func (*Success) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } - -func (m *Success) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -// * -// Response: Failure of the previous request -type Failure struct { - Code *FailureType `protobuf:"varint,1,opt,name=code,enum=FailureType" json:"code,omitempty"` - Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Failure) Reset() { *m = Failure{} } -func (m *Failure) String() string { return proto.CompactTextString(m) } -func (*Failure) ProtoMessage() {} -func (*Failure) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } - -func (m *Failure) GetCode() FailureType { - if m != nil && m.Code != nil { - return *m.Code - } - return FailureType_Failure_UnexpectedMessage -} - -func (m *Failure) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -// * -// Response: Device is waiting for HW button press. -// @next ButtonAck -// @next Cancel -type ButtonRequest struct { - Code *ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=ButtonRequestType" json:"code,omitempty"` - Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ButtonRequest) Reset() { *m = ButtonRequest{} } -func (m *ButtonRequest) String() string { return proto.CompactTextString(m) } -func (*ButtonRequest) ProtoMessage() {} -func (*ButtonRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } - -func (m *ButtonRequest) GetCode() ButtonRequestType { - if m != nil && m.Code != nil { - return *m.Code - } - return ButtonRequestType_ButtonRequest_Other -} - -func (m *ButtonRequest) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -// * -// Request: Computer agrees to wait for HW button press -// @prev ButtonRequest -type ButtonAck struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *ButtonAck) Reset() { *m = ButtonAck{} } -func (m *ButtonAck) String() string { return proto.CompactTextString(m) } -func (*ButtonAck) ProtoMessage() {} -func (*ButtonAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } - -// * -// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme -// @next PinMatrixAck -// @next Cancel -type PinMatrixRequest struct { - Type *PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=PinMatrixRequestType" json:"type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PinMatrixRequest) Reset() { *m = PinMatrixRequest{} } -func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) } -func (*PinMatrixRequest) ProtoMessage() {} -func (*PinMatrixRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } - -func (m *PinMatrixRequest) GetType() PinMatrixRequestType { - if m != nil && m.Type != nil { - return *m.Type - } - return PinMatrixRequestType_PinMatrixRequestType_Current -} - -// * -// Request: Computer responds with encoded PIN -// @prev PinMatrixRequest -type PinMatrixAck struct { - Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PinMatrixAck) Reset() { *m = PinMatrixAck{} } -func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) } -func (*PinMatrixAck) ProtoMessage() {} -func (*PinMatrixAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} } - -func (m *PinMatrixAck) GetPin() string { - if m != nil && m.Pin != nil { - return *m.Pin - } - return "" -} - -// * -// Request: Abort last operation that required user interaction -// @prev ButtonRequest -// @prev PinMatrixRequest -// @prev PassphraseRequest -type Cancel struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Cancel) Reset() { *m = Cancel{} } -func (m *Cancel) String() string { return proto.CompactTextString(m) } -func (*Cancel) ProtoMessage() {} -func (*Cancel) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} } - -// * -// Response: Device awaits encryption passphrase -// @next PassphraseAck -// @next Cancel -type PassphraseRequest struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *PassphraseRequest) Reset() { *m = PassphraseRequest{} } -func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) } -func (*PassphraseRequest) ProtoMessage() {} -func (*PassphraseRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{15} } - -// * -// Request: Send passphrase back -// @prev PassphraseRequest -type PassphraseAck struct { - Passphrase *string `protobuf:"bytes,1,req,name=passphrase" json:"passphrase,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PassphraseAck) Reset() { *m = PassphraseAck{} } -func (m *PassphraseAck) String() string { return proto.CompactTextString(m) } -func (*PassphraseAck) ProtoMessage() {} -func (*PassphraseAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{16} } - -func (m *PassphraseAck) GetPassphrase() string { - if m != nil && m.Passphrase != nil { - return *m.Passphrase - } - return "" -} - -// * -// Request: Request a sample of random data generated by hardware RNG. May be used for testing. -// @next ButtonRequest -// @next Entropy -// @next Failure -type GetEntropy struct { - Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetEntropy) Reset() { *m = GetEntropy{} } -func (m *GetEntropy) String() string { return proto.CompactTextString(m) } -func (*GetEntropy) ProtoMessage() {} -func (*GetEntropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{17} } - -func (m *GetEntropy) GetSize() uint32 { - if m != nil && m.Size != nil { - return *m.Size - } - return 0 -} - -// * -// Response: Reply with random data generated by internal RNG -// @prev GetEntropy -type Entropy struct { - Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Entropy) Reset() { *m = Entropy{} } -func (m *Entropy) String() string { return proto.CompactTextString(m) } -func (*Entropy) ProtoMessage() {} -func (*Entropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{18} } - -func (m *Entropy) GetEntropy() []byte { - if m != nil { - return m.Entropy - } - return nil -} - -// * -// Request: Ask device for public key corresponding to address_n path -// @next PassphraseRequest -// @next PublicKey -// @next Failure -type GetPublicKey struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - EcdsaCurveName *string `protobuf:"bytes,2,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` - ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` - CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetPublicKey) Reset() { *m = GetPublicKey{} } -func (m *GetPublicKey) String() string { return proto.CompactTextString(m) } -func (*GetPublicKey) ProtoMessage() {} -func (*GetPublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{19} } - -const Default_GetPublicKey_CoinName string = "Bitcoin" - -func (m *GetPublicKey) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *GetPublicKey) GetEcdsaCurveName() string { - if m != nil && m.EcdsaCurveName != nil { - return *m.EcdsaCurveName - } - return "" -} - -func (m *GetPublicKey) GetShowDisplay() bool { - if m != nil && m.ShowDisplay != nil { - return *m.ShowDisplay - } - return false -} - -func (m *GetPublicKey) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_GetPublicKey_CoinName -} - -// * -// Response: Contains public key derived from device private seed -// @prev GetPublicKey -type PublicKey struct { - Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"` - Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PublicKey) Reset() { *m = PublicKey{} } -func (m *PublicKey) String() string { return proto.CompactTextString(m) } -func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{20} } - -func (m *PublicKey) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *PublicKey) GetXpub() string { - if m != nil && m.Xpub != nil { - return *m.Xpub - } - return "" -} - -// * -// Request: Ask device for address corresponding to address_n path -// @next PassphraseRequest -// @next Address -// @next Failure -type GetAddress struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - CoinName *string `protobuf:"bytes,2,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` - Multisig *MultisigRedeemScriptType `protobuf:"bytes,4,opt,name=multisig" json:"multisig,omitempty"` - ScriptType *InputScriptType `protobuf:"varint,5,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetAddress) Reset() { *m = GetAddress{} } -func (m *GetAddress) String() string { return proto.CompactTextString(m) } -func (*GetAddress) ProtoMessage() {} -func (*GetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{21} } - -const Default_GetAddress_CoinName string = "Bitcoin" -const Default_GetAddress_ScriptType InputScriptType = InputScriptType_SPENDADDRESS - -func (m *GetAddress) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *GetAddress) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_GetAddress_CoinName -} - -func (m *GetAddress) GetShowDisplay() bool { - if m != nil && m.ShowDisplay != nil { - return *m.ShowDisplay - } - return false -} - -func (m *GetAddress) GetMultisig() *MultisigRedeemScriptType { - if m != nil { - return m.Multisig - } - return nil -} - -func (m *GetAddress) GetScriptType() InputScriptType { - if m != nil && m.ScriptType != nil { - return *m.ScriptType - } - return Default_GetAddress_ScriptType -} - -// * -// Request: Ask device for Ethereum address corresponding to address_n path -// @next PassphraseRequest -// @next EthereumAddress -// @next Failure -type EthereumGetAddress struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumGetAddress) Reset() { *m = EthereumGetAddress{} } -func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) } -func (*EthereumGetAddress) ProtoMessage() {} -func (*EthereumGetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{22} } - -func (m *EthereumGetAddress) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumGetAddress) GetShowDisplay() bool { - if m != nil && m.ShowDisplay != nil { - return *m.ShowDisplay - } - return false -} - -// * -// Response: Contains address derived from device private seed -// @prev GetAddress -type Address struct { - Address *string `protobuf:"bytes,1,req,name=address" json:"address,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Address) Reset() { *m = Address{} } -func (m *Address) String() string { return proto.CompactTextString(m) } -func (*Address) ProtoMessage() {} -func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{23} } - -func (m *Address) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -// * -// Response: Contains an Ethereum address derived from device private seed -// @prev EthereumGetAddress -type EthereumAddress struct { - Address []byte `protobuf:"bytes,1,req,name=address" json:"address,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumAddress) Reset() { *m = EthereumAddress{} } -func (m *EthereumAddress) String() string { return proto.CompactTextString(m) } -func (*EthereumAddress) ProtoMessage() {} -func (*EthereumAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{24} } - -func (m *EthereumAddress) GetAddress() []byte { - if m != nil { - return m.Address - } - return nil -} - -// * -// Request: Request device to wipe all sensitive data and settings -// @next ButtonRequest -type WipeDevice struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *WipeDevice) Reset() { *m = WipeDevice{} } -func (m *WipeDevice) String() string { return proto.CompactTextString(m) } -func (*WipeDevice) ProtoMessage() {} -func (*WipeDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{25} } - -// * -// Request: Load seed and related internal settings from the computer -// @next ButtonRequest -// @next Success -// @next Failure -type LoadDevice struct { - Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` - Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` - Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` - PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` - SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` - U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LoadDevice) Reset() { *m = LoadDevice{} } -func (m *LoadDevice) String() string { return proto.CompactTextString(m) } -func (*LoadDevice) ProtoMessage() {} -func (*LoadDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{26} } - -const Default_LoadDevice_Language string = "english" - -func (m *LoadDevice) GetMnemonic() string { - if m != nil && m.Mnemonic != nil { - return *m.Mnemonic - } - return "" -} - -func (m *LoadDevice) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *LoadDevice) GetPin() string { - if m != nil && m.Pin != nil { - return *m.Pin - } - return "" -} - -func (m *LoadDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *LoadDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_LoadDevice_Language -} - -func (m *LoadDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *LoadDevice) GetSkipChecksum() bool { - if m != nil && m.SkipChecksum != nil { - return *m.SkipChecksum - } - return false -} - -func (m *LoadDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -// * -// Request: Ask device to do initialization involving user interaction -// @next EntropyRequest -// @next Failure -type ResetDevice struct { - DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` - Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` - PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` - U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ResetDevice) Reset() { *m = ResetDevice{} } -func (m *ResetDevice) String() string { return proto.CompactTextString(m) } -func (*ResetDevice) ProtoMessage() {} -func (*ResetDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{27} } - -const Default_ResetDevice_Strength uint32 = 256 -const Default_ResetDevice_Language string = "english" - -func (m *ResetDevice) GetDisplayRandom() bool { - if m != nil && m.DisplayRandom != nil { - return *m.DisplayRandom - } - return false -} - -func (m *ResetDevice) GetStrength() uint32 { - if m != nil && m.Strength != nil { - return *m.Strength - } - return Default_ResetDevice_Strength -} - -func (m *ResetDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *ResetDevice) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *ResetDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_ResetDevice_Language -} - -func (m *ResetDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *ResetDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -func (m *ResetDevice) GetSkipBackup() bool { - if m != nil && m.SkipBackup != nil { - return *m.SkipBackup - } - return false -} - -// * -// Request: Perform backup of the device seed if not backed up using ResetDevice -// @next ButtonRequest -type BackupDevice struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *BackupDevice) Reset() { *m = BackupDevice{} } -func (m *BackupDevice) String() string { return proto.CompactTextString(m) } -func (*BackupDevice) ProtoMessage() {} -func (*BackupDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{28} } - -// * -// Response: Ask for additional entropy from host computer -// @prev ResetDevice -// @next EntropyAck -type EntropyRequest struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *EntropyRequest) Reset() { *m = EntropyRequest{} } -func (m *EntropyRequest) String() string { return proto.CompactTextString(m) } -func (*EntropyRequest) ProtoMessage() {} -func (*EntropyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{29} } - -// * -// Request: Provide additional entropy for seed generation function -// @prev EntropyRequest -// @next ButtonRequest -type EntropyAck struct { - Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EntropyAck) Reset() { *m = EntropyAck{} } -func (m *EntropyAck) String() string { return proto.CompactTextString(m) } -func (*EntropyAck) ProtoMessage() {} -func (*EntropyAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{30} } - -func (m *EntropyAck) GetEntropy() []byte { - if m != nil { - return m.Entropy - } - return nil -} - -// * -// Request: Start recovery workflow asking user for specific words of mnemonic -// Used to recovery device safely even on untrusted computer. -// @next WordRequest -type RecoveryDevice struct { - WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` - PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` - EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` - // 7 reserved for unused recovery method - Type *uint32 `protobuf:"varint,8,opt,name=type" json:"type,omitempty"` - U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RecoveryDevice) Reset() { *m = RecoveryDevice{} } -func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) } -func (*RecoveryDevice) ProtoMessage() {} -func (*RecoveryDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{31} } - -const Default_RecoveryDevice_Language string = "english" - -func (m *RecoveryDevice) GetWordCount() uint32 { - if m != nil && m.WordCount != nil { - return *m.WordCount - } - return 0 -} - -func (m *RecoveryDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *RecoveryDevice) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *RecoveryDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_RecoveryDevice_Language -} - -func (m *RecoveryDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *RecoveryDevice) GetEnforceWordlist() bool { - if m != nil && m.EnforceWordlist != nil { - return *m.EnforceWordlist - } - return false -} - -func (m *RecoveryDevice) GetType() uint32 { - if m != nil && m.Type != nil { - return *m.Type - } - return 0 -} - -func (m *RecoveryDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -func (m *RecoveryDevice) GetDryRun() bool { - if m != nil && m.DryRun != nil { - return *m.DryRun - } - return false -} - -// * -// Response: Device is waiting for user to enter word of the mnemonic -// Its position is shown only on device's internal display. -// @prev RecoveryDevice -// @prev WordAck -type WordRequest struct { - Type *WordRequestType `protobuf:"varint,1,opt,name=type,enum=WordRequestType" json:"type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *WordRequest) Reset() { *m = WordRequest{} } -func (m *WordRequest) String() string { return proto.CompactTextString(m) } -func (*WordRequest) ProtoMessage() {} -func (*WordRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} } - -func (m *WordRequest) GetType() WordRequestType { - if m != nil && m.Type != nil { - return *m.Type - } - return WordRequestType_WordRequestType_Plain -} - -// * -// Request: Computer replies with word from the mnemonic -// @prev WordRequest -// @next WordRequest -// @next Success -// @next Failure -type WordAck struct { - Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *WordAck) Reset() { *m = WordAck{} } -func (m *WordAck) String() string { return proto.CompactTextString(m) } -func (*WordAck) ProtoMessage() {} -func (*WordAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} } - -func (m *WordAck) GetWord() string { - if m != nil && m.Word != nil { - return *m.Word - } - return "" -} - -// * -// Request: Ask device to sign message -// @next MessageSignature -// @next Failure -type SignMessage struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"` - CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - ScriptType *InputScriptType `protobuf:"varint,4,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SignMessage) Reset() { *m = SignMessage{} } -func (m *SignMessage) String() string { return proto.CompactTextString(m) } -func (*SignMessage) ProtoMessage() {} -func (*SignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} } - -const Default_SignMessage_CoinName string = "Bitcoin" -const Default_SignMessage_ScriptType InputScriptType = InputScriptType_SPENDADDRESS - -func (m *SignMessage) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *SignMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *SignMessage) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_SignMessage_CoinName -} - -func (m *SignMessage) GetScriptType() InputScriptType { - if m != nil && m.ScriptType != nil { - return *m.ScriptType - } - return Default_SignMessage_ScriptType -} - -// * -// Request: Ask device to verify message -// @next Success -// @next Failure -type VerifyMessage struct { - Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` - CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *VerifyMessage) Reset() { *m = VerifyMessage{} } -func (m *VerifyMessage) String() string { return proto.CompactTextString(m) } -func (*VerifyMessage) ProtoMessage() {} -func (*VerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} } - -const Default_VerifyMessage_CoinName string = "Bitcoin" - -func (m *VerifyMessage) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -func (m *VerifyMessage) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *VerifyMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *VerifyMessage) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_VerifyMessage_CoinName -} - -// * -// Response: Signed message -// @prev SignMessage -type MessageSignature struct { - Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageSignature) Reset() { *m = MessageSignature{} } -func (m *MessageSignature) String() string { return proto.CompactTextString(m) } -func (*MessageSignature) ProtoMessage() {} -func (*MessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} } - -func (m *MessageSignature) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -func (m *MessageSignature) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -// * -// Request: Ask device to encrypt message -// @next EncryptedMessage -// @next Failure -type EncryptMessage struct { - Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` - Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` - DisplayOnly *bool `protobuf:"varint,3,opt,name=display_only,json=displayOnly" json:"display_only,omitempty"` - AddressN []uint32 `protobuf:"varint,4,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - CoinName *string `protobuf:"bytes,5,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EncryptMessage) Reset() { *m = EncryptMessage{} } -func (m *EncryptMessage) String() string { return proto.CompactTextString(m) } -func (*EncryptMessage) ProtoMessage() {} -func (*EncryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} } - -const Default_EncryptMessage_CoinName string = "Bitcoin" - -func (m *EncryptMessage) GetPubkey() []byte { - if m != nil { - return m.Pubkey - } - return nil -} - -func (m *EncryptMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *EncryptMessage) GetDisplayOnly() bool { - if m != nil && m.DisplayOnly != nil { - return *m.DisplayOnly - } - return false -} - -func (m *EncryptMessage) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EncryptMessage) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_EncryptMessage_CoinName -} - -// * -// Response: Encrypted message -// @prev EncryptMessage -type EncryptedMessage struct { - Nonce []byte `protobuf:"bytes,1,opt,name=nonce" json:"nonce,omitempty"` - Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` - Hmac []byte `protobuf:"bytes,3,opt,name=hmac" json:"hmac,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EncryptedMessage) Reset() { *m = EncryptedMessage{} } -func (m *EncryptedMessage) String() string { return proto.CompactTextString(m) } -func (*EncryptedMessage) ProtoMessage() {} -func (*EncryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} } - -func (m *EncryptedMessage) GetNonce() []byte { - if m != nil { - return m.Nonce - } - return nil -} - -func (m *EncryptedMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *EncryptedMessage) GetHmac() []byte { - if m != nil { - return m.Hmac - } - return nil -} - -// * -// Request: Ask device to decrypt message -// @next Success -// @next Failure -type DecryptMessage struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` - Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` - Hmac []byte `protobuf:"bytes,4,opt,name=hmac" json:"hmac,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DecryptMessage) Reset() { *m = DecryptMessage{} } -func (m *DecryptMessage) String() string { return proto.CompactTextString(m) } -func (*DecryptMessage) ProtoMessage() {} -func (*DecryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} } - -func (m *DecryptMessage) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *DecryptMessage) GetNonce() []byte { - if m != nil { - return m.Nonce - } - return nil -} - -func (m *DecryptMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *DecryptMessage) GetHmac() []byte { - if m != nil { - return m.Hmac - } - return nil -} - -// * -// Response: Decrypted message -// @prev DecryptedMessage -type DecryptedMessage struct { - Message []byte `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` - Address *string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DecryptedMessage) Reset() { *m = DecryptedMessage{} } -func (m *DecryptedMessage) String() string { return proto.CompactTextString(m) } -func (*DecryptedMessage) ProtoMessage() {} -func (*DecryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} } - -func (m *DecryptedMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *DecryptedMessage) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -// * -// Request: Ask device to encrypt or decrypt value of given key -// @next CipheredKeyValue -// @next Failure -type CipherKeyValue struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"` - Value []byte `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"` - Encrypt *bool `protobuf:"varint,4,opt,name=encrypt" json:"encrypt,omitempty"` - AskOnEncrypt *bool `protobuf:"varint,5,opt,name=ask_on_encrypt,json=askOnEncrypt" json:"ask_on_encrypt,omitempty"` - AskOnDecrypt *bool `protobuf:"varint,6,opt,name=ask_on_decrypt,json=askOnDecrypt" json:"ask_on_decrypt,omitempty"` - Iv []byte `protobuf:"bytes,7,opt,name=iv" json:"iv,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CipherKeyValue) Reset() { *m = CipherKeyValue{} } -func (m *CipherKeyValue) String() string { return proto.CompactTextString(m) } -func (*CipherKeyValue) ProtoMessage() {} -func (*CipherKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} } - -func (m *CipherKeyValue) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *CipherKeyValue) GetKey() string { - if m != nil && m.Key != nil { - return *m.Key - } - return "" -} - -func (m *CipherKeyValue) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *CipherKeyValue) GetEncrypt() bool { - if m != nil && m.Encrypt != nil { - return *m.Encrypt - } - return false -} - -func (m *CipherKeyValue) GetAskOnEncrypt() bool { - if m != nil && m.AskOnEncrypt != nil { - return *m.AskOnEncrypt - } - return false -} - -func (m *CipherKeyValue) GetAskOnDecrypt() bool { - if m != nil && m.AskOnDecrypt != nil { - return *m.AskOnDecrypt - } - return false -} - -func (m *CipherKeyValue) GetIv() []byte { - if m != nil { - return m.Iv - } - return nil -} - -// * -// Response: Return ciphered/deciphered value -// @prev CipherKeyValue -type CipheredKeyValue struct { - Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CipheredKeyValue) Reset() { *m = CipheredKeyValue{} } -func (m *CipheredKeyValue) String() string { return proto.CompactTextString(m) } -func (*CipheredKeyValue) ProtoMessage() {} -func (*CipheredKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} } - -func (m *CipheredKeyValue) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -// * -// Request: Estimated size of the transaction -// This behaves exactly like SignTx, which means that it can ask using TxRequest -// This call is non-blocking (except possible PassphraseRequest to unlock the seed) -// @next TxSize -// @next Failure -type EstimateTxSize struct { - OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"` - InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"` - CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EstimateTxSize) Reset() { *m = EstimateTxSize{} } -func (m *EstimateTxSize) String() string { return proto.CompactTextString(m) } -func (*EstimateTxSize) ProtoMessage() {} -func (*EstimateTxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} } - -const Default_EstimateTxSize_CoinName string = "Bitcoin" - -func (m *EstimateTxSize) GetOutputsCount() uint32 { - if m != nil && m.OutputsCount != nil { - return *m.OutputsCount - } - return 0 -} - -func (m *EstimateTxSize) GetInputsCount() uint32 { - if m != nil && m.InputsCount != nil { - return *m.InputsCount - } - return 0 -} - -func (m *EstimateTxSize) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_EstimateTxSize_CoinName -} - -// * -// Response: Estimated size of the transaction -// @prev EstimateTxSize -type TxSize struct { - TxSize *uint32 `protobuf:"varint,1,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxSize) Reset() { *m = TxSize{} } -func (m *TxSize) String() string { return proto.CompactTextString(m) } -func (*TxSize) ProtoMessage() {} -func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} } - -func (m *TxSize) GetTxSize() uint32 { - if m != nil && m.TxSize != nil { - return *m.TxSize - } - return 0 -} - -// * -// Request: Ask device to sign transaction -// @next PassphraseRequest -// @next PinMatrixRequest -// @next TxRequest -// @next Failure -type SignTx struct { - OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"` - InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"` - CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - Version *uint32 `protobuf:"varint,4,opt,name=version,def=1" json:"version,omitempty"` - LockTime *uint32 `protobuf:"varint,5,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SignTx) Reset() { *m = SignTx{} } -func (m *SignTx) String() string { return proto.CompactTextString(m) } -func (*SignTx) ProtoMessage() {} -func (*SignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} } - -const Default_SignTx_CoinName string = "Bitcoin" -const Default_SignTx_Version uint32 = 1 -const Default_SignTx_LockTime uint32 = 0 - -func (m *SignTx) GetOutputsCount() uint32 { - if m != nil && m.OutputsCount != nil { - return *m.OutputsCount - } - return 0 -} - -func (m *SignTx) GetInputsCount() uint32 { - if m != nil && m.InputsCount != nil { - return *m.InputsCount - } - return 0 -} - -func (m *SignTx) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_SignTx_CoinName -} - -func (m *SignTx) GetVersion() uint32 { - if m != nil && m.Version != nil { - return *m.Version - } - return Default_SignTx_Version -} - -func (m *SignTx) GetLockTime() uint32 { - if m != nil && m.LockTime != nil { - return *m.LockTime - } - return Default_SignTx_LockTime -} - -// * -// Request: Simplified transaction signing -// This method doesn't support streaming, so there are hardware limits in number of inputs and outputs. -// In case of success, the result is returned using TxRequest message. -// @next PassphraseRequest -// @next PinMatrixRequest -// @next TxRequest -// @next Failure -type SimpleSignTx struct { - Inputs []*TxInputType `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"` - Outputs []*TxOutputType `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` - Transactions []*TransactionType `protobuf:"bytes,3,rep,name=transactions" json:"transactions,omitempty"` - CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"` - Version *uint32 `protobuf:"varint,5,opt,name=version,def=1" json:"version,omitempty"` - LockTime *uint32 `protobuf:"varint,6,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SimpleSignTx) Reset() { *m = SimpleSignTx{} } -func (m *SimpleSignTx) String() string { return proto.CompactTextString(m) } -func (*SimpleSignTx) ProtoMessage() {} -func (*SimpleSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} } - -const Default_SimpleSignTx_CoinName string = "Bitcoin" -const Default_SimpleSignTx_Version uint32 = 1 -const Default_SimpleSignTx_LockTime uint32 = 0 - -func (m *SimpleSignTx) GetInputs() []*TxInputType { - if m != nil { - return m.Inputs - } - return nil -} - -func (m *SimpleSignTx) GetOutputs() []*TxOutputType { - if m != nil { - return m.Outputs - } - return nil -} - -func (m *SimpleSignTx) GetTransactions() []*TransactionType { - if m != nil { - return m.Transactions - } - return nil -} - -func (m *SimpleSignTx) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return Default_SimpleSignTx_CoinName -} - -func (m *SimpleSignTx) GetVersion() uint32 { - if m != nil && m.Version != nil { - return *m.Version - } - return Default_SimpleSignTx_Version -} - -func (m *SimpleSignTx) GetLockTime() uint32 { - if m != nil && m.LockTime != nil { - return *m.LockTime - } - return Default_SimpleSignTx_LockTime -} - -// * -// Response: Device asks for information for signing transaction or returns the last result -// If request_index is set, device awaits TxAck message (with fields filled in according to request_type) -// If signature_index is set, 'signature' contains signed input of signature_index's input -// @prev SignTx -// @prev SimpleSignTx -// @prev TxAck -type TxRequest struct { - RequestType *RequestType `protobuf:"varint,1,opt,name=request_type,json=requestType,enum=RequestType" json:"request_type,omitempty"` - Details *TxRequestDetailsType `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"` - Serialized *TxRequestSerializedType `protobuf:"bytes,3,opt,name=serialized" json:"serialized,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxRequest) Reset() { *m = TxRequest{} } -func (m *TxRequest) String() string { return proto.CompactTextString(m) } -func (*TxRequest) ProtoMessage() {} -func (*TxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} } - -func (m *TxRequest) GetRequestType() RequestType { - if m != nil && m.RequestType != nil { - return *m.RequestType - } - return RequestType_TXINPUT -} - -func (m *TxRequest) GetDetails() *TxRequestDetailsType { - if m != nil { - return m.Details - } - return nil -} - -func (m *TxRequest) GetSerialized() *TxRequestSerializedType { - if m != nil { - return m.Serialized - } - return nil -} - -// * -// Request: Reported transaction data -// @prev TxRequest -// @next TxRequest -type TxAck struct { - Tx *TransactionType `protobuf:"bytes,1,opt,name=tx" json:"tx,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxAck) Reset() { *m = TxAck{} } -func (m *TxAck) String() string { return proto.CompactTextString(m) } -func (*TxAck) ProtoMessage() {} -func (*TxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{48} } - -func (m *TxAck) GetTx() *TransactionType { - if m != nil { - return m.Tx - } - return nil -} - -// * -// Request: Ask device to sign transaction -// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. -// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. -// @next PassphraseRequest -// @next PinMatrixRequest -// @next EthereumTxRequest -// @next Failure -type EthereumSignTx struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` - GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` - GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` - To []byte `protobuf:"bytes,5,opt,name=to" json:"to,omitempty"` - Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` - DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` - DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` - ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumSignTx) Reset() { *m = EthereumSignTx{} } -func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) } -func (*EthereumSignTx) ProtoMessage() {} -func (*EthereumSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{49} } - -func (m *EthereumSignTx) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumSignTx) GetNonce() []byte { - if m != nil { - return m.Nonce - } - return nil -} - -func (m *EthereumSignTx) GetGasPrice() []byte { - if m != nil { - return m.GasPrice - } - return nil -} - -func (m *EthereumSignTx) GetGasLimit() []byte { - if m != nil { - return m.GasLimit - } - return nil -} - -func (m *EthereumSignTx) GetTo() []byte { - if m != nil { - return m.To - } - return nil -} - -func (m *EthereumSignTx) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *EthereumSignTx) GetDataInitialChunk() []byte { - if m != nil { - return m.DataInitialChunk - } - return nil -} - -func (m *EthereumSignTx) GetDataLength() uint32 { - if m != nil && m.DataLength != nil { - return *m.DataLength - } - return 0 -} - -func (m *EthereumSignTx) GetChainId() uint32 { - if m != nil && m.ChainId != nil { - return *m.ChainId - } - return 0 -} - -// * -// Response: Device asks for more data from transaction payload, or returns the signature. -// If data_length is set, device awaits that many more bytes of payload. -// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. -// @prev EthereumSignTx -// @next EthereumTxAck -type EthereumTxRequest struct { - DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` - SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` - SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` - SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumTxRequest) Reset() { *m = EthereumTxRequest{} } -func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) } -func (*EthereumTxRequest) ProtoMessage() {} -func (*EthereumTxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{50} } - -func (m *EthereumTxRequest) GetDataLength() uint32 { - if m != nil && m.DataLength != nil { - return *m.DataLength - } - return 0 -} - -func (m *EthereumTxRequest) GetSignatureV() uint32 { - if m != nil && m.SignatureV != nil { - return *m.SignatureV - } - return 0 -} - -func (m *EthereumTxRequest) GetSignatureR() []byte { - if m != nil { - return m.SignatureR - } - return nil -} - -func (m *EthereumTxRequest) GetSignatureS() []byte { - if m != nil { - return m.SignatureS - } - return nil -} - -// * -// Request: Transaction payload data. -// @prev EthereumTxRequest -// @next EthereumTxRequest -type EthereumTxAck struct { - DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumTxAck) Reset() { *m = EthereumTxAck{} } -func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) } -func (*EthereumTxAck) ProtoMessage() {} -func (*EthereumTxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} } - -func (m *EthereumTxAck) GetDataChunk() []byte { - if m != nil { - return m.DataChunk - } - return nil -} - -// * -// Request: Ask device to sign message -// @next EthereumMessageSignature -// @next Failure -type EthereumSignMessage struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumSignMessage) Reset() { *m = EthereumSignMessage{} } -func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) } -func (*EthereumSignMessage) ProtoMessage() {} -func (*EthereumSignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} } - -func (m *EthereumSignMessage) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumSignMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -// * -// Request: Ask device to verify message -// @next Success -// @next Failure -type EthereumVerifyMessage struct { - Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumVerifyMessage) Reset() { *m = EthereumVerifyMessage{} } -func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) } -func (*EthereumVerifyMessage) ProtoMessage() {} -func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} } - -func (m *EthereumVerifyMessage) GetAddress() []byte { - if m != nil { - return m.Address - } - return nil -} - -func (m *EthereumVerifyMessage) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *EthereumVerifyMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -// * -// Response: Signed message -// @prev EthereumSignMessage -type EthereumMessageSignature struct { - Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EthereumMessageSignature) Reset() { *m = EthereumMessageSignature{} } -func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) } -func (*EthereumMessageSignature) ProtoMessage() {} -func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} } - -func (m *EthereumMessageSignature) GetAddress() []byte { - if m != nil { - return m.Address - } - return nil -} - -func (m *EthereumMessageSignature) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -// * -// Request: Ask device to sign identity -// @next SignedIdentity -// @next Failure -type SignIdentity struct { - Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"` - ChallengeHidden []byte `protobuf:"bytes,2,opt,name=challenge_hidden,json=challengeHidden" json:"challenge_hidden,omitempty"` - ChallengeVisual *string `protobuf:"bytes,3,opt,name=challenge_visual,json=challengeVisual" json:"challenge_visual,omitempty"` - EcdsaCurveName *string `protobuf:"bytes,4,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SignIdentity) Reset() { *m = SignIdentity{} } -func (m *SignIdentity) String() string { return proto.CompactTextString(m) } -func (*SignIdentity) ProtoMessage() {} -func (*SignIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} } - -func (m *SignIdentity) GetIdentity() *IdentityType { - if m != nil { - return m.Identity - } - return nil -} - -func (m *SignIdentity) GetChallengeHidden() []byte { - if m != nil { - return m.ChallengeHidden - } - return nil -} - -func (m *SignIdentity) GetChallengeVisual() string { - if m != nil && m.ChallengeVisual != nil { - return *m.ChallengeVisual - } - return "" -} - -func (m *SignIdentity) GetEcdsaCurveName() string { - if m != nil && m.EcdsaCurveName != nil { - return *m.EcdsaCurveName - } - return "" -} - -// * -// Response: Device provides signed identity -// @prev SignIdentity -type SignedIdentity struct { - Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature" json:"signature,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SignedIdentity) Reset() { *m = SignedIdentity{} } -func (m *SignedIdentity) String() string { return proto.CompactTextString(m) } -func (*SignedIdentity) ProtoMessage() {} -func (*SignedIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} } - -func (m *SignedIdentity) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -func (m *SignedIdentity) GetPublicKey() []byte { - if m != nil { - return m.PublicKey - } - return nil -} - -func (m *SignedIdentity) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -// * -// Request: Ask device to generate ECDH session key -// @next ECDHSessionKey -// @next Failure -type GetECDHSessionKey struct { - Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"` - PeerPublicKey []byte `protobuf:"bytes,2,opt,name=peer_public_key,json=peerPublicKey" json:"peer_public_key,omitempty"` - EcdsaCurveName *string `protobuf:"bytes,3,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GetECDHSessionKey) Reset() { *m = GetECDHSessionKey{} } -func (m *GetECDHSessionKey) String() string { return proto.CompactTextString(m) } -func (*GetECDHSessionKey) ProtoMessage() {} -func (*GetECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} } - -func (m *GetECDHSessionKey) GetIdentity() *IdentityType { - if m != nil { - return m.Identity - } - return nil -} - -func (m *GetECDHSessionKey) GetPeerPublicKey() []byte { - if m != nil { - return m.PeerPublicKey - } - return nil -} - -func (m *GetECDHSessionKey) GetEcdsaCurveName() string { - if m != nil && m.EcdsaCurveName != nil { - return *m.EcdsaCurveName - } - return "" -} - -// * -// Response: Device provides ECDH session key -// @prev GetECDHSessionKey -type ECDHSessionKey struct { - SessionKey []byte `protobuf:"bytes,1,opt,name=session_key,json=sessionKey" json:"session_key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ECDHSessionKey) Reset() { *m = ECDHSessionKey{} } -func (m *ECDHSessionKey) String() string { return proto.CompactTextString(m) } -func (*ECDHSessionKey) ProtoMessage() {} -func (*ECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} } - -func (m *ECDHSessionKey) GetSessionKey() []byte { - if m != nil { - return m.SessionKey - } - return nil -} - -// * -// Request: Set U2F counter -// @next Success -type SetU2FCounter struct { - U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SetU2FCounter) Reset() { *m = SetU2FCounter{} } -func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) } -func (*SetU2FCounter) ProtoMessage() {} -func (*SetU2FCounter) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} } - -func (m *SetU2FCounter) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -// * -// Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload) -// @next Success -// @next FirmwareRequest -// @next Failure -type FirmwareErase struct { - Length *uint32 `protobuf:"varint,1,opt,name=length" json:"length,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FirmwareErase) Reset() { *m = FirmwareErase{} } -func (m *FirmwareErase) String() string { return proto.CompactTextString(m) } -func (*FirmwareErase) ProtoMessage() {} -func (*FirmwareErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} } - -func (m *FirmwareErase) GetLength() uint32 { - if m != nil && m.Length != nil { - return *m.Length - } - return 0 -} - -// * -// Response: Ask for firmware chunk -// @next FirmwareUpload -type FirmwareRequest struct { - Offset *uint32 `protobuf:"varint,1,opt,name=offset" json:"offset,omitempty"` - Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FirmwareRequest) Reset() { *m = FirmwareRequest{} } -func (m *FirmwareRequest) String() string { return proto.CompactTextString(m) } -func (*FirmwareRequest) ProtoMessage() {} -func (*FirmwareRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} } - -func (m *FirmwareRequest) GetOffset() uint32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return 0 -} - -func (m *FirmwareRequest) GetLength() uint32 { - if m != nil && m.Length != nil { - return *m.Length - } - return 0 -} - -// * -// Request: Send firmware in binary form to the device -// @next Success -// @next Failure -type FirmwareUpload struct { - Payload []byte `protobuf:"bytes,1,req,name=payload" json:"payload,omitempty"` - Hash []byte `protobuf:"bytes,2,opt,name=hash" json:"hash,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FirmwareUpload) Reset() { *m = FirmwareUpload{} } -func (m *FirmwareUpload) String() string { return proto.CompactTextString(m) } -func (*FirmwareUpload) ProtoMessage() {} -func (*FirmwareUpload) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} } - -func (m *FirmwareUpload) GetPayload() []byte { - if m != nil { - return m.Payload - } - return nil -} - -func (m *FirmwareUpload) GetHash() []byte { - if m != nil { - return m.Hash - } - return nil -} - -// * -// Request: Perform a device self-test -// @next Success -// @next Failure -type SelfTest struct { - Payload []byte `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SelfTest) Reset() { *m = SelfTest{} } -func (m *SelfTest) String() string { return proto.CompactTextString(m) } -func (*SelfTest) ProtoMessage() {} -func (*SelfTest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} } - -func (m *SelfTest) GetPayload() []byte { - if m != nil { - return m.Payload - } - return nil -} - -// * -// Request: "Press" the button on the device -// @next Success -type DebugLinkDecision struct { - YesNo *bool `protobuf:"varint,1,req,name=yes_no,json=yesNo" json:"yes_no,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkDecision) Reset() { *m = DebugLinkDecision{} } -func (m *DebugLinkDecision) String() string { return proto.CompactTextString(m) } -func (*DebugLinkDecision) ProtoMessage() {} -func (*DebugLinkDecision) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{64} } - -func (m *DebugLinkDecision) GetYesNo() bool { - if m != nil && m.YesNo != nil { - return *m.YesNo - } - return false -} - -// * -// Request: Computer asks for device state -// @next DebugLinkState -type DebugLinkGetState struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkGetState) Reset() { *m = DebugLinkGetState{} } -func (m *DebugLinkGetState) String() string { return proto.CompactTextString(m) } -func (*DebugLinkGetState) ProtoMessage() {} -func (*DebugLinkGetState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{65} } - -// * -// Response: Device current state -// @prev DebugLinkGetState -type DebugLinkState struct { - Layout []byte `protobuf:"bytes,1,opt,name=layout" json:"layout,omitempty"` - Pin *string `protobuf:"bytes,2,opt,name=pin" json:"pin,omitempty"` - Matrix *string `protobuf:"bytes,3,opt,name=matrix" json:"matrix,omitempty"` - Mnemonic *string `protobuf:"bytes,4,opt,name=mnemonic" json:"mnemonic,omitempty"` - Node *HDNodeType `protobuf:"bytes,5,opt,name=node" json:"node,omitempty"` - PassphraseProtection *bool `protobuf:"varint,6,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - ResetWord *string `protobuf:"bytes,7,opt,name=reset_word,json=resetWord" json:"reset_word,omitempty"` - ResetEntropy []byte `protobuf:"bytes,8,opt,name=reset_entropy,json=resetEntropy" json:"reset_entropy,omitempty"` - RecoveryFakeWord *string `protobuf:"bytes,9,opt,name=recovery_fake_word,json=recoveryFakeWord" json:"recovery_fake_word,omitempty"` - RecoveryWordPos *uint32 `protobuf:"varint,10,opt,name=recovery_word_pos,json=recoveryWordPos" json:"recovery_word_pos,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkState) Reset() { *m = DebugLinkState{} } -func (m *DebugLinkState) String() string { return proto.CompactTextString(m) } -func (*DebugLinkState) ProtoMessage() {} -func (*DebugLinkState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} } - -func (m *DebugLinkState) GetLayout() []byte { - if m != nil { - return m.Layout - } - return nil -} - -func (m *DebugLinkState) GetPin() string { - if m != nil && m.Pin != nil { - return *m.Pin - } - return "" -} - -func (m *DebugLinkState) GetMatrix() string { - if m != nil && m.Matrix != nil { - return *m.Matrix - } - return "" -} - -func (m *DebugLinkState) GetMnemonic() string { - if m != nil && m.Mnemonic != nil { - return *m.Mnemonic - } - return "" -} - -func (m *DebugLinkState) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *DebugLinkState) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *DebugLinkState) GetResetWord() string { - if m != nil && m.ResetWord != nil { - return *m.ResetWord - } - return "" -} - -func (m *DebugLinkState) GetResetEntropy() []byte { - if m != nil { - return m.ResetEntropy - } - return nil -} - -func (m *DebugLinkState) GetRecoveryFakeWord() string { - if m != nil && m.RecoveryFakeWord != nil { - return *m.RecoveryFakeWord - } - return "" -} - -func (m *DebugLinkState) GetRecoveryWordPos() uint32 { - if m != nil && m.RecoveryWordPos != nil { - return *m.RecoveryWordPos - } - return 0 -} - -// * -// Request: Ask device to restart -type DebugLinkStop struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkStop) Reset() { *m = DebugLinkStop{} } -func (m *DebugLinkStop) String() string { return proto.CompactTextString(m) } -func (*DebugLinkStop) ProtoMessage() {} -func (*DebugLinkStop) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} } - -// * -// Response: Device wants host to log event -type DebugLinkLog struct { - Level *uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"` - Bucket *string `protobuf:"bytes,2,opt,name=bucket" json:"bucket,omitempty"` - Text *string `protobuf:"bytes,3,opt,name=text" json:"text,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkLog) Reset() { *m = DebugLinkLog{} } -func (m *DebugLinkLog) String() string { return proto.CompactTextString(m) } -func (*DebugLinkLog) ProtoMessage() {} -func (*DebugLinkLog) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} } - -func (m *DebugLinkLog) GetLevel() uint32 { - if m != nil && m.Level != nil { - return *m.Level - } - return 0 -} - -func (m *DebugLinkLog) GetBucket() string { - if m != nil && m.Bucket != nil { - return *m.Bucket - } - return "" -} - -func (m *DebugLinkLog) GetText() string { - if m != nil && m.Text != nil { - return *m.Text - } - return "" -} - -// * -// Request: Read memory from device -// @next DebugLinkMemory -type DebugLinkMemoryRead struct { - Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"` - Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkMemoryRead) Reset() { *m = DebugLinkMemoryRead{} } -func (m *DebugLinkMemoryRead) String() string { return proto.CompactTextString(m) } -func (*DebugLinkMemoryRead) ProtoMessage() {} -func (*DebugLinkMemoryRead) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} } - -func (m *DebugLinkMemoryRead) GetAddress() uint32 { - if m != nil && m.Address != nil { - return *m.Address - } - return 0 -} - -func (m *DebugLinkMemoryRead) GetLength() uint32 { - if m != nil && m.Length != nil { - return *m.Length - } - return 0 -} - -// * -// Response: Device sends memory back -// @prev DebugLinkMemoryRead -type DebugLinkMemory struct { - Memory []byte `protobuf:"bytes,1,opt,name=memory" json:"memory,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkMemory) Reset() { *m = DebugLinkMemory{} } -func (m *DebugLinkMemory) String() string { return proto.CompactTextString(m) } -func (*DebugLinkMemory) ProtoMessage() {} -func (*DebugLinkMemory) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} } - -func (m *DebugLinkMemory) GetMemory() []byte { - if m != nil { - return m.Memory - } - return nil -} - -// * -// Request: Write memory to device. -// WARNING: Writing to the wrong location can irreparably break the device. -type DebugLinkMemoryWrite struct { - Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"` - Memory []byte `protobuf:"bytes,2,opt,name=memory" json:"memory,omitempty"` - Flash *bool `protobuf:"varint,3,opt,name=flash" json:"flash,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkMemoryWrite) Reset() { *m = DebugLinkMemoryWrite{} } -func (m *DebugLinkMemoryWrite) String() string { return proto.CompactTextString(m) } -func (*DebugLinkMemoryWrite) ProtoMessage() {} -func (*DebugLinkMemoryWrite) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} } - -func (m *DebugLinkMemoryWrite) GetAddress() uint32 { - if m != nil && m.Address != nil { - return *m.Address - } - return 0 -} - -func (m *DebugLinkMemoryWrite) GetMemory() []byte { - if m != nil { - return m.Memory - } - return nil -} - -func (m *DebugLinkMemoryWrite) GetFlash() bool { - if m != nil && m.Flash != nil { - return *m.Flash - } - return false -} - -// * -// Request: Erase block of flash on device -// WARNING: Writing to the wrong location can irreparably break the device. -type DebugLinkFlashErase struct { - Sector *uint32 `protobuf:"varint,1,opt,name=sector" json:"sector,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DebugLinkFlashErase) Reset() { *m = DebugLinkFlashErase{} } -func (m *DebugLinkFlashErase) String() string { return proto.CompactTextString(m) } -func (*DebugLinkFlashErase) ProtoMessage() {} -func (*DebugLinkFlashErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{72} } - -func (m *DebugLinkFlashErase) GetSector() uint32 { - if m != nil && m.Sector != nil { - return *m.Sector - } - return 0 -} - -func init() { - proto.RegisterType((*Initialize)(nil), "Initialize") - proto.RegisterType((*GetFeatures)(nil), "GetFeatures") - proto.RegisterType((*Features)(nil), "Features") - proto.RegisterType((*ClearSession)(nil), "ClearSession") - proto.RegisterType((*ApplySettings)(nil), "ApplySettings") - proto.RegisterType((*ApplyFlags)(nil), "ApplyFlags") - proto.RegisterType((*ChangePin)(nil), "ChangePin") - proto.RegisterType((*Ping)(nil), "Ping") - proto.RegisterType((*Success)(nil), "Success") - proto.RegisterType((*Failure)(nil), "Failure") - proto.RegisterType((*ButtonRequest)(nil), "ButtonRequest") - proto.RegisterType((*ButtonAck)(nil), "ButtonAck") - proto.RegisterType((*PinMatrixRequest)(nil), "PinMatrixRequest") - proto.RegisterType((*PinMatrixAck)(nil), "PinMatrixAck") - proto.RegisterType((*Cancel)(nil), "Cancel") - proto.RegisterType((*PassphraseRequest)(nil), "PassphraseRequest") - proto.RegisterType((*PassphraseAck)(nil), "PassphraseAck") - proto.RegisterType((*GetEntropy)(nil), "GetEntropy") - proto.RegisterType((*Entropy)(nil), "Entropy") - proto.RegisterType((*GetPublicKey)(nil), "GetPublicKey") - proto.RegisterType((*PublicKey)(nil), "PublicKey") - proto.RegisterType((*GetAddress)(nil), "GetAddress") - proto.RegisterType((*EthereumGetAddress)(nil), "EthereumGetAddress") - proto.RegisterType((*Address)(nil), "Address") - proto.RegisterType((*EthereumAddress)(nil), "EthereumAddress") - proto.RegisterType((*WipeDevice)(nil), "WipeDevice") - proto.RegisterType((*LoadDevice)(nil), "LoadDevice") - proto.RegisterType((*ResetDevice)(nil), "ResetDevice") - proto.RegisterType((*BackupDevice)(nil), "BackupDevice") - proto.RegisterType((*EntropyRequest)(nil), "EntropyRequest") - proto.RegisterType((*EntropyAck)(nil), "EntropyAck") - proto.RegisterType((*RecoveryDevice)(nil), "RecoveryDevice") - proto.RegisterType((*WordRequest)(nil), "WordRequest") - proto.RegisterType((*WordAck)(nil), "WordAck") - proto.RegisterType((*SignMessage)(nil), "SignMessage") - proto.RegisterType((*VerifyMessage)(nil), "VerifyMessage") - proto.RegisterType((*MessageSignature)(nil), "MessageSignature") - proto.RegisterType((*EncryptMessage)(nil), "EncryptMessage") - proto.RegisterType((*EncryptedMessage)(nil), "EncryptedMessage") - proto.RegisterType((*DecryptMessage)(nil), "DecryptMessage") - proto.RegisterType((*DecryptedMessage)(nil), "DecryptedMessage") - proto.RegisterType((*CipherKeyValue)(nil), "CipherKeyValue") - proto.RegisterType((*CipheredKeyValue)(nil), "CipheredKeyValue") - proto.RegisterType((*EstimateTxSize)(nil), "EstimateTxSize") - proto.RegisterType((*TxSize)(nil), "TxSize") - proto.RegisterType((*SignTx)(nil), "SignTx") - proto.RegisterType((*SimpleSignTx)(nil), "SimpleSignTx") - proto.RegisterType((*TxRequest)(nil), "TxRequest") - proto.RegisterType((*TxAck)(nil), "TxAck") - proto.RegisterType((*EthereumSignTx)(nil), "EthereumSignTx") - proto.RegisterType((*EthereumTxRequest)(nil), "EthereumTxRequest") - proto.RegisterType((*EthereumTxAck)(nil), "EthereumTxAck") - proto.RegisterType((*EthereumSignMessage)(nil), "EthereumSignMessage") - proto.RegisterType((*EthereumVerifyMessage)(nil), "EthereumVerifyMessage") - proto.RegisterType((*EthereumMessageSignature)(nil), "EthereumMessageSignature") - proto.RegisterType((*SignIdentity)(nil), "SignIdentity") - proto.RegisterType((*SignedIdentity)(nil), "SignedIdentity") - proto.RegisterType((*GetECDHSessionKey)(nil), "GetECDHSessionKey") - proto.RegisterType((*ECDHSessionKey)(nil), "ECDHSessionKey") - proto.RegisterType((*SetU2FCounter)(nil), "SetU2FCounter") - proto.RegisterType((*FirmwareErase)(nil), "FirmwareErase") - proto.RegisterType((*FirmwareRequest)(nil), "FirmwareRequest") - proto.RegisterType((*FirmwareUpload)(nil), "FirmwareUpload") - proto.RegisterType((*SelfTest)(nil), "SelfTest") - proto.RegisterType((*DebugLinkDecision)(nil), "DebugLinkDecision") - proto.RegisterType((*DebugLinkGetState)(nil), "DebugLinkGetState") - proto.RegisterType((*DebugLinkState)(nil), "DebugLinkState") - proto.RegisterType((*DebugLinkStop)(nil), "DebugLinkStop") - proto.RegisterType((*DebugLinkLog)(nil), "DebugLinkLog") - proto.RegisterType((*DebugLinkMemoryRead)(nil), "DebugLinkMemoryRead") - proto.RegisterType((*DebugLinkMemory)(nil), "DebugLinkMemory") - proto.RegisterType((*DebugLinkMemoryWrite)(nil), "DebugLinkMemoryWrite") - proto.RegisterType((*DebugLinkFlashErase)(nil), "DebugLinkFlashErase") - proto.RegisterEnum("MessageType", MessageType_name, MessageType_value) -} - -func init() { proto.RegisterFile("messages.proto", fileDescriptor1) } - -var fileDescriptor1 = []byte{ - // 3424 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5a, 0xcb, 0x6f, 0xdc, 0x46, - 0x9a, 0x5f, 0x76, 0xb7, 0xfa, 0xf1, 0x35, 0xbb, 0x55, 0xa2, 0x2d, 0xbb, 0x2d, 0x5b, 0xb6, 0x4c, - 0xc9, 0xb6, 0x64, 0x27, 0xed, 0x44, 0x79, 0x6c, 0xd6, 0xbb, 0x79, 0xc8, 0x7a, 0xd8, 0xde, 0xd8, - 0x8e, 0xc0, 0x56, 0x9c, 0xdb, 0x12, 0x14, 0x59, 0xea, 0xae, 0x55, 0x37, 0xc9, 0xf0, 0xa1, 0xa8, - 0x7d, 0xd8, 0xeb, 0xee, 0x65, 0x81, 0xec, 0x69, 0x73, 0x1a, 0xe4, 0x36, 0x19, 0x04, 0x18, 0x0c, - 0x30, 0x18, 0x60, 0x72, 0x9a, 0x3f, 0x60, 0xfe, 0x8b, 0x39, 0xce, 0x1f, 0x30, 0xe7, 0x41, 0x3d, - 0x48, 0x16, 0x29, 0xb6, 0x6c, 0x27, 0xc0, 0x5c, 0x04, 0xd6, 0x57, 0xbf, 0xfe, 0xea, 0x7b, 0xd5, - 0x57, 0x5f, 0x7d, 0x25, 0xe8, 0x4e, 0x70, 0x18, 0x5a, 0x43, 0x1c, 0xf6, 0xfd, 0xc0, 0x8b, 0xbc, - 0xa5, 0x76, 0x34, 0xf5, 0x93, 0x81, 0xae, 0x02, 0x3c, 0x71, 0x49, 0x44, 0xac, 0x31, 0x79, 0x89, - 0xf5, 0x0e, 0xb4, 0x1f, 0xe1, 0x68, 0x0f, 0x5b, 0x51, 0x1c, 0xe0, 0x50, 0xff, 0x69, 0x0e, 0x9a, - 0xc9, 0x40, 0xbb, 0x04, 0xf5, 0x13, 0xec, 0x3a, 0x5e, 0xd0, 0x53, 0x56, 0x94, 0xf5, 0x96, 0x21, - 0x46, 0xda, 0x2a, 0x74, 0x26, 0xd6, 0x7f, 0x7a, 0x81, 0x79, 0x82, 0x83, 0x90, 0x78, 0x6e, 0xaf, - 0xb2, 0xa2, 0xac, 0x77, 0x0c, 0x95, 0x11, 0x5f, 0x70, 0x1a, 0x03, 0x11, 0x57, 0x02, 0x55, 0x05, - 0x88, 0x12, 0x25, 0x90, 0x6f, 0x45, 0xf6, 0x28, 0x05, 0xd5, 0x38, 0x88, 0x11, 0x13, 0xd0, 0x1d, - 0x98, 0x3f, 0xf4, 0xbc, 0x68, 0xec, 0x59, 0x0e, 0x0e, 0xcc, 0x89, 0xe7, 0xe0, 0xde, 0xdc, 0x8a, - 0xb2, 0xde, 0x34, 0xba, 0x19, 0xf9, 0x99, 0xe7, 0x60, 0xed, 0x2a, 0xb4, 0x1c, 0x7c, 0x42, 0x6c, - 0x6c, 0x12, 0xa7, 0x57, 0x67, 0x22, 0x37, 0x39, 0xe1, 0x89, 0xa3, 0xdd, 0x82, 0xae, 0x4f, 0x5c, - 0x93, 0xda, 0x00, 0xdb, 0x11, 0x5d, 0xab, 0xc1, 0x98, 0x74, 0x7c, 0xe2, 0xee, 0xa7, 0x44, 0xed, - 0x3d, 0x58, 0xf4, 0xad, 0x30, 0xf4, 0x47, 0x81, 0x15, 0x62, 0x19, 0xdd, 0x64, 0xe8, 0x8b, 0xd9, - 0xa4, 0xf4, 0xa3, 0x25, 0x68, 0x8e, 0x2d, 0x77, 0x18, 0x5b, 0x43, 0xdc, 0x6b, 0xf1, 0x75, 0x93, - 0xb1, 0x76, 0x11, 0xe6, 0xc6, 0xd6, 0x21, 0x1e, 0xf7, 0x80, 0x4d, 0xf0, 0x81, 0x76, 0x03, 0xe6, - 0x6c, 0x8f, 0xb8, 0x61, 0xaf, 0xbd, 0x52, 0x5d, 0x6f, 0x6f, 0xb6, 0xfa, 0xdb, 0x1e, 0x71, 0x0f, - 0xa6, 0x3e, 0x36, 0x38, 0x5d, 0x5b, 0x81, 0x36, 0x49, 0xbd, 0xe4, 0xf4, 0x54, 0xb6, 0xba, 0x4c, - 0xa2, 0x8b, 0x06, 0xf8, 0x84, 0x30, 0xb3, 0x75, 0x56, 0x94, 0x75, 0xd5, 0x48, 0xc7, 0x05, 0x93, - 0x8d, 0xac, 0x70, 0xd4, 0xeb, 0x32, 0x88, 0x64, 0xb2, 0xc7, 0x56, 0x38, 0xa2, 0x4c, 0xc8, 0xc4, - 0xf7, 0x82, 0x08, 0x3b, 0xbd, 0x79, 0xb6, 0x46, 0x3a, 0xd6, 0x96, 0x01, 0xa8, 0xc5, 0x6c, 0xcb, - 0x1e, 0x61, 0xa7, 0x87, 0xd8, 0x6c, 0xcb, 0x27, 0xee, 0x36, 0x23, 0x68, 0xf7, 0x60, 0x41, 0xb2, - 0x94, 0x40, 0x2d, 0x30, 0x14, 0xca, 0x26, 0x04, 0x78, 0x03, 0xd0, 0x11, 0x09, 0x26, 0xdf, 0x58, - 0x01, 0x35, 0x2a, 0x0e, 0xb1, 0x1b, 0xf5, 0x34, 0x86, 0x9d, 0x4f, 0xe8, 0xfb, 0x9c, 0xac, 0xdd, - 0x04, 0xd5, 0xc5, 0xd8, 0x09, 0xcd, 0x43, 0xcb, 0x3e, 0x8e, 0xfd, 0xde, 0x05, 0xae, 0x3a, 0xa3, - 0x3d, 0x64, 0x24, 0x6a, 0xd3, 0xa3, 0xb1, 0x35, 0x0c, 0x7b, 0x17, 0x59, 0xb8, 0xf0, 0x81, 0xde, - 0x05, 0x75, 0x7b, 0x8c, 0xad, 0x60, 0x80, 0x43, 0x6a, 0x04, 0xfd, 0x7f, 0x14, 0xe8, 0x6c, 0xf9, - 0xfe, 0x78, 0x3a, 0xc0, 0x51, 0x44, 0xdc, 0x61, 0x98, 0xf3, 0x93, 0x32, 0xcb, 0x4f, 0x15, 0xd9, - 0x4f, 0xb7, 0xa0, 0x1b, 0xd3, 0x38, 0x48, 0xf5, 0x61, 0x61, 0xdc, 0x34, 0x3a, 0x71, 0x88, 0xf7, - 0x53, 0xa2, 0x76, 0x1d, 0x60, 0xe4, 0x4d, 0x70, 0x68, 0x07, 0x18, 0xf3, 0x20, 0x56, 0x0d, 0x89, - 0xa2, 0xeb, 0x00, 0x4c, 0x92, 0x3d, 0x2a, 0x68, 0x26, 0xbe, 0x22, 0x8b, 0xbf, 0x0a, 0xad, 0xed, - 0x91, 0xe5, 0x0e, 0xf1, 0x3e, 0x71, 0xe9, 0xd6, 0x0b, 0xf0, 0xc4, 0x3b, 0xe1, 0x72, 0x36, 0x0d, - 0x31, 0xd2, 0x7f, 0xa3, 0x40, 0x6d, 0x9f, 0xb8, 0x43, 0xad, 0x07, 0x0d, 0xb1, 0xc9, 0x85, 0x26, - 0xc9, 0x90, 0xfa, 0xe5, 0x30, 0x8e, 0x22, 0x2f, 0x17, 0xeb, 0x15, 0xee, 0x17, 0x3e, 0x21, 0x45, - 0xee, 0xd9, 0x5d, 0x51, 0x7d, 0xa3, 0x5d, 0x51, 0x9b, 0xbd, 0x2b, 0xf4, 0x55, 0x68, 0x0c, 0x62, - 0xdb, 0xc6, 0x61, 0x38, 0x5b, 0x5a, 0x7d, 0x17, 0x1a, 0x7b, 0x16, 0x19, 0xc7, 0x01, 0xd6, 0x56, - 0xa0, 0x66, 0xd3, 0xcd, 0x4d, 0x11, 0xdd, 0x4d, 0xb5, 0x2f, 0xe8, 0x6c, 0x57, 0xb0, 0x19, 0x99, - 0x4d, 0x25, 0xcf, 0xe6, 0x73, 0xe8, 0x3c, 0x64, 0xba, 0x19, 0xf8, 0xeb, 0x18, 0x87, 0x91, 0x76, - 0x3b, 0xc7, 0x4c, 0xeb, 0xe7, 0x66, 0x25, 0x96, 0x1a, 0xd4, 0x1c, 0x2b, 0xb2, 0x04, 0x3f, 0xf6, - 0xad, 0xb7, 0xa1, 0xc5, 0xe1, 0x5b, 0xf6, 0xb1, 0xfe, 0x31, 0xa0, 0x7d, 0xe2, 0x3e, 0xb3, 0xa2, - 0x80, 0x9c, 0x26, 0xcc, 0x37, 0xa0, 0x46, 0x33, 0xaa, 0x60, 0xbe, 0xd8, 0x2f, 0x02, 0x38, 0x7f, - 0x0a, 0xd1, 0x57, 0x40, 0x4d, 0x67, 0xb7, 0xec, 0x63, 0x0d, 0x41, 0xd5, 0x27, 0x6e, 0x4f, 0x59, - 0xa9, 0xac, 0xb7, 0x0c, 0xfa, 0xa9, 0x37, 0xa1, 0xbe, 0x6d, 0xb9, 0x36, 0x1e, 0xeb, 0x17, 0x60, - 0x21, 0x8b, 0x29, 0xc1, 0x4a, 0xbf, 0x0f, 0x9d, 0x8c, 0x48, 0x39, 0x5c, 0x07, 0x90, 0xc2, 0x91, - 0x33, 0x92, 0x28, 0xfa, 0x0a, 0xc0, 0x23, 0x1c, 0xed, 0xba, 0x51, 0xe0, 0xf9, 0x53, 0xaa, 0x5f, - 0x48, 0x5e, 0x72, 0x5c, 0xc7, 0x60, 0xdf, 0xd4, 0x31, 0xc9, 0x74, 0x0f, 0x1a, 0x98, 0x7f, 0x32, - 0x84, 0x6a, 0x24, 0x43, 0xfd, 0x57, 0x0a, 0xa8, 0x8f, 0x70, 0xb4, 0x1f, 0x1f, 0x8e, 0x89, 0xfd, - 0x39, 0x9e, 0xd2, 0xec, 0x6a, 0x39, 0x4e, 0x80, 0xc3, 0xd0, 0xa4, 0xf2, 0x57, 0xd7, 0x3b, 0x46, - 0x53, 0x10, 0x9e, 0x6b, 0xeb, 0x80, 0xb0, 0xed, 0x84, 0x96, 0x69, 0xc7, 0xc1, 0x09, 0x36, 0x5d, - 0x6b, 0x92, 0xb8, 0xa8, 0xcb, 0xe8, 0xdb, 0x94, 0xfc, 0xdc, 0x9a, 0x60, 0xba, 0xbd, 0xc3, 0x91, - 0xf7, 0x8d, 0xe9, 0x90, 0xd0, 0x1f, 0x5b, 0x53, 0x11, 0x6f, 0x6d, 0x4a, 0xdb, 0xe1, 0x24, 0x6d, - 0x0d, 0x5a, 0x34, 0x09, 0x72, 0x2e, 0x34, 0xc2, 0x5a, 0x0f, 0x1a, 0x0f, 0x49, 0x44, 0x69, 0x46, - 0x93, 0xfe, 0xa5, 0x8c, 0xf4, 0xcf, 0xa0, 0x95, 0x09, 0x77, 0x03, 0x6a, 0x2e, 0x77, 0x77, 0x65, - 0xbd, 0xbd, 0xd9, 0xee, 0x3f, 0xde, 0x79, 0xee, 0x39, 0x22, 0x74, 0x5c, 0xe1, 0xe7, 0x53, 0x3f, - 0x3e, 0x4c, 0xfc, 0x4c, 0xbf, 0xf5, 0xbf, 0x2a, 0xcc, 0x54, 0x5b, 0x5c, 0x89, 0xf3, 0x15, 0xcc, - 0xc9, 0x54, 0x99, 0x21, 0xd3, 0xeb, 0x28, 0xf7, 0x01, 0x34, 0x27, 0xf1, 0x38, 0x22, 0x21, 0x19, - 0x32, 0xdd, 0xda, 0x9b, 0x57, 0xfa, 0xcf, 0x04, 0xc1, 0xc0, 0x0e, 0xc6, 0x93, 0x81, 0x1d, 0x10, - 0x9f, 0xc7, 0x50, 0x0a, 0xd5, 0x3e, 0x85, 0x76, 0xc8, 0xe8, 0x26, 0x8b, 0xbc, 0x39, 0x16, 0x79, - 0xa8, 0xff, 0xc4, 0xf5, 0xe3, 0x28, 0xfb, 0xc1, 0x03, 0x75, 0xb0, 0xbf, 0xfb, 0x7c, 0x67, 0x6b, - 0x67, 0xc7, 0xd8, 0x1d, 0x0c, 0x0c, 0x08, 0xd3, 0x19, 0xfd, 0x00, 0xb4, 0xdd, 0x68, 0x84, 0x03, - 0x1c, 0x4f, 0x5e, 0x57, 0xe7, 0xa2, 0x36, 0x95, 0x33, 0xda, 0xd0, 0x50, 0x4a, 0x58, 0xf5, 0xa0, - 0x21, 0x7e, 0x29, 0x82, 0x32, 0x19, 0xea, 0xf7, 0x60, 0x3e, 0x59, 0x7a, 0x06, 0x58, 0xcd, 0xc0, - 0x2a, 0xc0, 0x57, 0xc4, 0xc7, 0x3b, 0xec, 0xdc, 0xd6, 0xff, 0xaf, 0x02, 0xf0, 0xd4, 0xb3, 0x1c, - 0x3e, 0xa4, 0x09, 0x7c, 0xe2, 0xe2, 0x89, 0xe7, 0x12, 0x3b, 0x49, 0xe0, 0xc9, 0x38, 0x0d, 0x81, - 0x0a, 0x33, 0x6a, 0x49, 0x08, 0x88, 0xad, 0x57, 0x65, 0xbf, 0xa3, 0x9f, 0x3f, 0x2b, 0xad, 0x69, - 0xab, 0xd2, 0x21, 0x32, 0xc7, 0x03, 0x01, 0xbb, 0xc3, 0x31, 0x09, 0x47, 0x65, 0xa7, 0x49, 0x5d, - 0x3e, 0x4d, 0x56, 0xa1, 0x13, 0x1e, 0x13, 0xdf, 0xb4, 0x47, 0xd8, 0x3e, 0x0e, 0xe3, 0x89, 0x28, - 0x41, 0x54, 0x4a, 0xdc, 0x16, 0x34, 0xed, 0x06, 0xb4, 0xe3, 0xcd, 0x23, 0xd3, 0xf6, 0x62, 0x37, - 0xc2, 0x01, 0xab, 0x3b, 0x3a, 0x06, 0xc4, 0x9b, 0x47, 0xdb, 0x9c, 0xa2, 0xff, 0xb6, 0x02, 0x6d, - 0x03, 0x87, 0x38, 0x12, 0x46, 0xb9, 0x05, 0x5d, 0xe1, 0x21, 0x33, 0xb0, 0x5c, 0xc7, 0x9b, 0x88, - 0x33, 0xa3, 0x23, 0xa8, 0x06, 0x23, 0x6a, 0x37, 0xa0, 0x19, 0x46, 0x01, 0x76, 0x87, 0xd1, 0x88, - 0x17, 0x6c, 0x0f, 0xaa, 0x9b, 0x1f, 0x7c, 0x68, 0xa4, 0xc4, 0xd9, 0xd6, 0xa8, 0x9e, 0x63, 0x8d, - 0xb3, 0x07, 0x48, 0xad, 0xec, 0x00, 0xf9, 0x05, 0x46, 0x2b, 0xd8, 0xa3, 0x51, 0xb4, 0x07, 0x05, - 0x30, 0xab, 0x8a, 0x7a, 0x81, 0x17, 0x6a, 0x40, 0x49, 0xbc, 0x5c, 0xa0, 0x85, 0x01, 0xff, 0x12, - 0x41, 0x85, 0xa0, 0x2b, 0xf2, 0x5f, 0x92, 0x64, 0x6f, 0x03, 0x08, 0x0a, 0xcd, 0xb0, 0xb9, 0xa4, - 0xa8, 0xc8, 0x49, 0xf1, 0x4f, 0x15, 0xe8, 0x1a, 0xd8, 0xf6, 0x4e, 0x70, 0x30, 0x15, 0xd6, 0x5f, - 0x06, 0xf8, 0xc6, 0x0b, 0x1c, 0x2e, 0x9f, 0x38, 0xd1, 0x5b, 0x94, 0xc2, 0xc4, 0x9b, 0x6d, 0xd4, - 0xca, 0x1b, 0x19, 0xb5, 0xfa, 0x2a, 0xa3, 0xd6, 0x5e, 0x69, 0xd4, 0x39, 0xd9, 0xa8, 0x1b, 0x80, - 0xb0, 0x7b, 0xe4, 0x05, 0x36, 0x36, 0xa9, 0xac, 0x63, 0x12, 0x46, 0xcc, 0xea, 0x4d, 0x63, 0x5e, - 0xd0, 0xbf, 0x12, 0x64, 0x9a, 0x39, 0x59, 0xca, 0xe1, 0x81, 0xc8, 0xbe, 0x8b, 0x3e, 0x69, 0x9d, - 0xf1, 0xc9, 0x65, 0x68, 0x38, 0xc1, 0xd4, 0x0c, 0x62, 0x97, 0xd5, 0xbd, 0x4d, 0xa3, 0xee, 0x04, - 0x53, 0x23, 0x76, 0xf5, 0xf7, 0xa0, 0x4d, 0x39, 0x27, 0x27, 0xe9, 0x5a, 0xee, 0x24, 0x45, 0x7d, - 0x69, 0x4e, 0x3a, 0x44, 0x97, 0xa1, 0x41, 0x27, 0xa8, 0x6f, 0x34, 0xa8, 0x51, 0x81, 0x45, 0x8a, - 0x61, 0xdf, 0xfa, 0x8f, 0x0a, 0xb4, 0x07, 0x64, 0xe8, 0x3e, 0x13, 0x15, 0xd0, 0xb9, 0x49, 0x2d, - 0x57, 0x43, 0xb0, 0xcc, 0x93, 0x14, 0x4e, 0xb9, 0x14, 0x5f, 0x9d, 0x95, 0xe2, 0x0b, 0x89, 0xb8, - 0xf6, 0xc6, 0x89, 0xf8, 0xbf, 0x15, 0xe8, 0xbc, 0xc0, 0x01, 0x39, 0x9a, 0x26, 0xf2, 0xe6, 0x92, - 0xa1, 0x22, 0x65, 0x4e, 0xed, 0x1a, 0xb4, 0x42, 0x32, 0x74, 0xd9, 0x7d, 0x8c, 0x45, 0x8c, 0x6a, - 0x64, 0x04, 0x59, 0x95, 0x2a, 0x8f, 0xd3, 0x52, 0x55, 0x66, 0x9e, 0xa0, 0xff, 0x0e, 0x48, 0x88, - 0x30, 0x90, 0x79, 0xfe, 0x1c, 0x59, 0xf4, 0x1f, 0x14, 0xba, 0xa9, 0xec, 0x60, 0xea, 0x47, 0x89, - 0x5a, 0x97, 0xa0, 0xee, 0xc7, 0x87, 0xc7, 0x38, 0xd9, 0x45, 0x62, 0x54, 0xac, 0xe2, 0x24, 0xb1, - 0x6f, 0x82, 0x9a, 0x64, 0x32, 0xcf, 0x1d, 0xa7, 0xc7, 0xa7, 0xa0, 0x7d, 0xe1, 0x8e, 0x0b, 0x55, - 0x48, 0xed, 0xbc, 0x43, 0x7a, 0x6e, 0x96, 0xda, 0x2f, 0x00, 0x09, 0x49, 0xb1, 0x93, 0xc8, 0x7a, - 0x11, 0xe6, 0x5c, 0xcf, 0xb5, 0xb1, 0x10, 0x95, 0x0f, 0xce, 0x91, 0x54, 0x83, 0xda, 0x68, 0x62, - 0xd9, 0xc2, 0xee, 0xec, 0x5b, 0xff, 0x1a, 0xba, 0x3b, 0x38, 0x67, 0x81, 0x73, 0x03, 0x31, 0x5d, - 0xb2, 0x32, 0x63, 0xc9, 0x6a, 0xf9, 0x92, 0x35, 0x69, 0xc9, 0x3d, 0x40, 0x62, 0xc9, 0x4c, 0x95, - 0x42, 0xad, 0x2d, 0x71, 0x90, 0x7c, 0x5b, 0xc9, 0xf9, 0x56, 0xff, 0xb3, 0x02, 0xdd, 0x6d, 0xe2, - 0x8f, 0x70, 0xf0, 0x39, 0x9e, 0xbe, 0xb0, 0xc6, 0xf1, 0x2b, 0x64, 0x47, 0x50, 0xa5, 0x7e, 0xe5, - 0x5c, 0xe8, 0x27, 0xd5, 0xe6, 0x84, 0xfe, 0x4e, 0x48, 0xcd, 0x07, 0x3c, 0x93, 0x32, 0xf9, 0xc4, - 0xb1, 0x90, 0x0c, 0xb5, 0x35, 0xe8, 0x5a, 0xe1, 0xb1, 0xe9, 0xb9, 0x66, 0x02, 0xe0, 0x77, 0x7a, - 0xd5, 0x0a, 0x8f, 0xbf, 0x70, 0x77, 0xcf, 0xa0, 0x1c, 0xae, 0xa6, 0x48, 0x52, 0x1c, 0x25, 0x54, - 0xd7, 0xba, 0x50, 0x21, 0x27, 0xec, 0x60, 0x50, 0x8d, 0x0a, 0x39, 0xd1, 0xd7, 0x01, 0x71, 0x65, - 0xb0, 0x93, 0xaa, 0x93, 0xca, 0xa7, 0x48, 0xf2, 0xe9, 0xff, 0x05, 0xdd, 0xdd, 0x30, 0x22, 0x13, - 0x2b, 0xc2, 0x07, 0xa7, 0x03, 0xf2, 0x12, 0xd3, 0x23, 0xda, 0x8b, 0x23, 0x3f, 0x8e, 0xc2, 0x34, - 0xa3, 0xd3, 0xc2, 0x59, 0x15, 0x44, 0x9e, 0xd4, 0x6f, 0x82, 0x4a, 0x5c, 0x09, 0x53, 0x61, 0x98, - 0x36, 0xa7, 0x71, 0xc8, 0x6b, 0x25, 0x13, 0xfd, 0x26, 0xd4, 0xc5, 0xba, 0x97, 0xa1, 0x11, 0x9d, - 0x9a, 0xa2, 0x54, 0xa7, 0xd9, 0xb4, 0x1e, 0xb1, 0x09, 0xfd, 0xf7, 0x0a, 0xd4, 0xe9, 0xf6, 0x3c, - 0x38, 0xfd, 0xc7, 0xca, 0xa6, 0x5d, 0x85, 0x46, 0xae, 0x2b, 0xf3, 0x40, 0x79, 0xd7, 0x48, 0x28, - 0xda, 0x75, 0x68, 0x8d, 0x3d, 0xfb, 0xd8, 0x8c, 0x88, 0xd8, 0x69, 0x9d, 0x07, 0xca, 0x3b, 0x46, - 0x93, 0xd2, 0x0e, 0xc8, 0x04, 0xeb, 0x7f, 0x53, 0x40, 0x1d, 0x90, 0x89, 0x3f, 0xc6, 0x42, 0xf6, - 0x35, 0xa8, 0x73, 0x11, 0x58, 0x2c, 0xb5, 0x37, 0xd5, 0xfe, 0xc1, 0x29, 0xcb, 0x99, 0x2c, 0xcd, - 0x8b, 0x39, 0xed, 0x0e, 0x34, 0x84, 0x32, 0xbd, 0x0a, 0x83, 0x75, 0xfa, 0x07, 0xa7, 0x5f, 0x30, - 0x0a, 0xc3, 0x25, 0xb3, 0xda, 0xfb, 0xa0, 0x46, 0x81, 0xe5, 0x86, 0x16, 0x3b, 0x09, 0xc3, 0x5e, - 0x95, 0xa1, 0x51, 0xff, 0x20, 0x23, 0xb2, 0x1f, 0xe4, 0x50, 0xaf, 0x97, 0x16, 0x65, 0xc5, 0xe7, - 0xce, 0x57, 0xbc, 0x7e, 0x56, 0xf1, 0x5f, 0x2b, 0xd0, 0x3a, 0x48, 0x2f, 0x8a, 0xf7, 0x41, 0x0d, - 0xf8, 0xa7, 0x29, 0x1d, 0x73, 0x6a, 0x5f, 0x3e, 0xe2, 0xda, 0x41, 0x36, 0xd0, 0xee, 0x43, 0xc3, - 0xc1, 0x91, 0x45, 0xc6, 0xa1, 0xa8, 0x63, 0x17, 0xfb, 0x29, 0xb7, 0x1d, 0x3e, 0xc1, 0x0d, 0x21, - 0x50, 0xda, 0x47, 0x00, 0x21, 0x0e, 0x92, 0x36, 0x51, 0x95, 0xfd, 0xa6, 0x97, 0xfd, 0x66, 0x90, - 0xce, 0xb1, 0x9f, 0x49, 0x58, 0x7d, 0x03, 0xe6, 0x0e, 0xd8, 0x95, 0x74, 0x05, 0x2a, 0xd1, 0x29, - 0x13, 0xad, 0xcc, 0x82, 0x95, 0xe8, 0x54, 0xff, 0xdf, 0x0a, 0x74, 0x93, 0x0a, 0x5e, 0xf8, 0xf3, - 0x67, 0xa4, 0xb6, 0xab, 0xd0, 0x1a, 0x5a, 0xa1, 0xe9, 0x07, 0xc4, 0x4e, 0xd2, 0x44, 0x73, 0x68, - 0x85, 0xfb, 0x74, 0x9c, 0x4c, 0x8e, 0xc9, 0x84, 0x44, 0x22, 0xc5, 0xd1, 0xc9, 0xa7, 0x74, 0x4c, - 0x37, 0x78, 0xe4, 0x31, 0x67, 0xa8, 0x46, 0x25, 0xf2, 0xb2, 0xcd, 0x5c, 0x97, 0x93, 0xcd, 0x5b, - 0xa0, 0xd1, 0xeb, 0xbb, 0x29, 0x9a, 0x64, 0xa6, 0x3d, 0x8a, 0xdd, 0x63, 0x91, 0x16, 0x10, 0x9d, - 0x11, 0x6d, 0xcf, 0x6d, 0x4a, 0xa7, 0x25, 0x0c, 0x43, 0x8f, 0x79, 0x45, 0x2c, 0xca, 0x6c, 0x4a, - 0x7a, 0xca, 0xcb, 0xe1, 0x2b, 0xd0, 0xb4, 0x47, 0x16, 0x71, 0x4d, 0xe2, 0x88, 0x02, 0xa7, 0xc1, - 0xc6, 0x4f, 0x1c, 0xfd, 0xff, 0x15, 0x58, 0x48, 0xec, 0x91, 0x39, 0xbb, 0xc0, 0x51, 0x39, 0xc3, - 0x91, 0x16, 0xaa, 0xc9, 0x81, 0x69, 0x9e, 0x88, 0xae, 0x29, 0xa4, 0xa4, 0x17, 0x79, 0x40, 0x20, - 0x6c, 0x94, 0x01, 0x8c, 0x3c, 0x20, 0x4c, 0x1a, 0x4d, 0x29, 0x69, 0xa0, 0xf7, 0xa1, 0x93, 0x09, - 0x46, 0x9d, 0xbb, 0x0c, 0x4c, 0x02, 0x61, 0x0c, 0x9e, 0xfc, 0x5a, 0x94, 0xc2, 0xac, 0xa0, 0x3f, - 0x85, 0x0b, 0xb2, 0x63, 0x7f, 0x59, 0x05, 0xa5, 0x13, 0x58, 0x4c, 0xb8, 0x9d, 0x5b, 0xe1, 0xa8, - 0xbf, 0xb8, 0xc2, 0xd1, 0x0d, 0xe8, 0x25, 0x4b, 0xbd, 0xaa, 0x86, 0x79, 0xdd, 0xd5, 0xf4, 0x9f, - 0x58, 0xd2, 0x1a, 0xba, 0x4f, 0x1c, 0xec, 0x46, 0x24, 0x9a, 0x6a, 0x1b, 0xd0, 0x24, 0xe2, 0x5b, - 0xec, 0x8f, 0x4e, 0x3f, 0x99, 0xe4, 0xf7, 0x73, 0x92, 0x41, 0x91, 0x3d, 0xb2, 0xc6, 0xd4, 0xf7, - 0xd8, 0x1c, 0x11, 0xc7, 0xc1, 0xae, 0x58, 0x60, 0x3e, 0xa5, 0x3f, 0x66, 0xe4, 0x3c, 0xf4, 0x84, - 0x84, 0xb1, 0x35, 0x16, 0x97, 0xd2, 0x0c, 0xfa, 0x82, 0x91, 0x4b, 0xdb, 0x2a, 0xb5, 0xb2, 0xb6, - 0x8a, 0x3e, 0x84, 0x2e, 0x15, 0x1d, 0x3b, 0xa9, 0xf0, 0xb3, 0x2b, 0xb9, 0x65, 0x00, 0x9f, 0x75, - 0x4e, 0xcc, 0xe4, 0x10, 0x57, 0x8d, 0x96, 0x9f, 0xf6, 0x52, 0x72, 0x46, 0xaa, 0x16, 0x8d, 0xf4, - 0xad, 0x02, 0x0b, 0x8f, 0x70, 0xb4, 0xbb, 0xbd, 0xf3, 0x58, 0x34, 0x5a, 0xe9, 0x6f, 0xde, 0xc0, - 0x52, 0xb7, 0x61, 0xde, 0xc7, 0x38, 0x30, 0xcf, 0x88, 0xd0, 0xa1, 0xe4, 0xac, 0xa5, 0x53, 0xa6, - 0x7b, 0xb5, 0x54, 0xf7, 0x77, 0xa1, 0x5b, 0x10, 0x87, 0xee, 0x13, 0x3e, 0x32, 0xb3, 0xfa, 0x13, - 0xc2, 0x14, 0xa0, 0xbf, 0x03, 0x9d, 0x01, 0x8e, 0xbe, 0xdc, 0xdc, 0x93, 0x2e, 0x91, 0xf2, 0x8d, - 0x46, 0x39, 0x73, 0xeb, 0xbe, 0x03, 0x9d, 0x3d, 0xd1, 0xa9, 0xde, 0x65, 0x3d, 0xdf, 0x4b, 0x50, - 0xcf, 0xed, 0x74, 0x31, 0xd2, 0xb7, 0x60, 0x3e, 0x01, 0x26, 0x99, 0xe1, 0x12, 0xd4, 0xbd, 0xa3, - 0xa3, 0x10, 0x27, 0xf7, 0x43, 0x31, 0x92, 0x58, 0x54, 0x72, 0x2c, 0x3e, 0x81, 0x6e, 0xc2, 0xe2, - 0x4b, 0x7f, 0xec, 0x59, 0x0e, 0x75, 0xa6, 0x6f, 0x4d, 0xe9, 0x67, 0xd2, 0x2f, 0x11, 0x43, 0x56, - 0x16, 0x5a, 0xe1, 0x48, 0xd8, 0x90, 0x7d, 0xeb, 0x6b, 0xd0, 0x1c, 0xe0, 0xf1, 0xd1, 0x01, 0x5d, - 0x3b, 0xf7, 0x4b, 0x45, 0xfa, 0xa5, 0x7e, 0x17, 0x16, 0x76, 0xf0, 0x61, 0x3c, 0x7c, 0x4a, 0xdc, - 0xe3, 0x1d, 0x6c, 0xf3, 0x97, 0x83, 0x45, 0xa8, 0x4f, 0x71, 0x68, 0xba, 0x1e, 0x5b, 0xa7, 0x69, - 0xcc, 0x4d, 0x71, 0xf8, 0xdc, 0xd3, 0x2f, 0x48, 0xd8, 0x47, 0x38, 0x1a, 0x44, 0x56, 0x84, 0xf5, - 0xbf, 0x54, 0x68, 0xc5, 0x2b, 0xa8, 0x8c, 0xc4, 0x34, 0xb2, 0xa6, 0x5e, 0x1c, 0x25, 0x35, 0x3f, - 0x1f, 0x25, 0xbd, 0x97, 0x4a, 0xd6, 0x7b, 0xb9, 0x04, 0xf5, 0x09, 0xeb, 0x8a, 0x0a, 0xa7, 0x8a, - 0x51, 0xae, 0xc5, 0x53, 0x9b, 0xd1, 0xe2, 0x99, 0x9b, 0xd5, 0xe2, 0x99, 0x79, 0xdb, 0xae, 0x9f, - 0x73, 0xdb, 0x5e, 0x06, 0x08, 0x70, 0x88, 0x23, 0x76, 0x13, 0x66, 0xe7, 0x45, 0xcb, 0x68, 0x31, - 0x0a, 0xbd, 0x74, 0xd2, 0xaa, 0x8b, 0x4f, 0x27, 0x3d, 0x81, 0x26, 0xd3, 0x4c, 0x65, 0xc4, 0xa4, - 0x8f, 0xfa, 0x16, 0x68, 0x81, 0xe8, 0x0b, 0x98, 0x47, 0xd6, 0x31, 0xbf, 0x55, 0x8b, 0xb7, 0x20, - 0x94, 0xcc, 0xec, 0x59, 0xc7, 0xec, 0x5a, 0xad, 0xdd, 0x85, 0x85, 0x14, 0xcd, 0x9a, 0x07, 0xbe, - 0x17, 0xb2, 0x7b, 0x72, 0xc7, 0x98, 0x4f, 0x26, 0x28, 0x70, 0xdf, 0x0b, 0xf5, 0x79, 0xe8, 0x48, - 0x36, 0xf6, 0x7c, 0x7d, 0x1f, 0xd4, 0x94, 0xf0, 0xd4, 0x1b, 0xb2, 0x0b, 0x3e, 0x3e, 0xc1, 0xe3, - 0xe4, 0x35, 0x81, 0x0d, 0xa8, 0x79, 0x0f, 0x63, 0xfb, 0x18, 0x47, 0xc2, 0xe6, 0x62, 0xc4, 0x6e, - 0xf3, 0xf8, 0x34, 0x12, 0x46, 0x67, 0xdf, 0xfa, 0x23, 0xb8, 0x90, 0x72, 0x7c, 0x86, 0x27, 0x5e, - 0x30, 0x35, 0x30, 0x8f, 0x39, 0x39, 0x81, 0x74, 0xb2, 0x04, 0x32, 0x2b, 0x6e, 0x37, 0x60, 0xbe, - 0xc0, 0x88, 0xb9, 0x99, 0x7d, 0x25, 0x01, 0xc1, 0x47, 0xfa, 0x7f, 0xc0, 0xc5, 0x02, 0xf4, 0xab, - 0x80, 0x44, 0xf8, 0xfc, 0x45, 0x05, 0xa7, 0x8a, 0xcc, 0x49, 0xbc, 0xa6, 0x84, 0x23, 0x71, 0x5b, - 0xe4, 0x03, 0xfd, 0x6d, 0x49, 0xa7, 0x3d, 0x4a, 0x49, 0x37, 0x6d, 0x88, 0xed, 0xc8, 0x4b, 0x76, - 0xb8, 0x18, 0xdd, 0xfd, 0x71, 0x11, 0xda, 0xe2, 0x1c, 0x61, 0x75, 0xd8, 0x0a, 0x5c, 0x92, 0x86, - 0x66, 0xf6, 0x60, 0x8a, 0xfe, 0x69, 0xa9, 0xf6, 0xed, 0x1f, 0x7a, 0x8a, 0xb6, 0x94, 0x5e, 0x9e, - 0x19, 0x62, 0x9f, 0xb8, 0x43, 0xa4, 0x88, 0xb9, 0x65, 0xb8, 0x20, 0xcf, 0x89, 0x57, 0x10, 0x54, - 0x59, 0xaa, 0x7d, 0x57, 0x32, 0x2d, 0xde, 0x39, 0x50, 0x55, 0x4c, 0xdf, 0x80, 0x45, 0x79, 0x3a, - 0x7d, 0x14, 0x42, 0x35, 0xc1, 0xbe, 0x20, 0x5c, 0xd6, 0x2e, 0x45, 0x73, 0x02, 0x71, 0x07, 0xae, - 0xe4, 0x56, 0x90, 0x13, 0x17, 0xaa, 0x2f, 0x35, 0x29, 0xe8, 0x8f, 0x14, 0xb8, 0x0e, 0x4b, 0x65, - 0x40, 0x9e, 0x75, 0x50, 0x43, 0x42, 0x6e, 0xc0, 0xd5, 0x32, 0xa4, 0x48, 0x71, 0xa8, 0xb9, 0xd4, - 0xfc, 0x2e, 0x81, 0x16, 0xe4, 0xcb, 0x5e, 0x23, 0x50, 0xab, 0xdc, 0x40, 0xc9, 0x34, 0x08, 0x0b, - 0xe8, 0xd0, 0x2b, 0x30, 0x48, 0x8f, 0x05, 0xd4, 0x16, 0x2c, 0x0a, 0x56, 0xca, 0x00, 0xaa, 0x60, - 0x52, 0x90, 0x22, 0xeb, 0x22, 0xa3, 0x8e, 0x60, 0x71, 0x13, 0x2e, 0xcb, 0x08, 0xa9, 0xa7, 0x8a, - 0xba, 0x02, 0x72, 0x0d, 0xb4, 0x9c, 0x27, 0x59, 0xf1, 0x8b, 0xe6, 0xc5, 0xec, 0x5a, 0x5e, 0x4e, - 0xf9, 0xc2, 0x83, 0xd0, 0x52, 0x9d, 0x62, 0x9a, 0x8a, 0x76, 0x1d, 0x2e, 0xe6, 0x2c, 0x27, 0x9e, - 0xd7, 0xd1, 0x82, 0x10, 0xf4, 0x36, 0x5c, 0x2b, 0x44, 0x52, 0xee, 0x31, 0x09, 0x69, 0x29, 0xae, - 0x57, 0x8a, 0xdb, 0xb2, 0x8f, 0xd1, 0x05, 0xee, 0xa9, 0xdf, 0x95, 0xc8, 0xcc, 0x1f, 0x97, 0xd0, - 0xc5, 0x72, 0xbb, 0xa5, 0xe5, 0x2b, 0x5a, 0x14, 0xcb, 0x5c, 0x85, 0x85, 0x3c, 0x80, 0xf2, 0xbf, - 0x94, 0x6a, 0x9c, 0x8b, 0x97, 0x7c, 0xcf, 0x00, 0x5d, 0x16, 0xa8, 0x82, 0xff, 0xe4, 0x57, 0x59, - 0xd4, 0x13, 0x98, 0xd5, 0x7c, 0x88, 0xe6, 0x1e, 0x6a, 0xd1, 0x95, 0x72, 0x50, 0xee, 0x11, 0x0f, - 0x2d, 0x09, 0x81, 0x57, 0xf3, 0x1a, 0xa5, 0x4f, 0x77, 0xe8, 0xaa, 0x64, 0x94, 0x42, 0x34, 0x64, - 0xaf, 0xb1, 0xe8, 0x5a, 0xf9, 0xae, 0xca, 0x1e, 0x49, 0xd0, 0x72, 0x79, 0xd4, 0x26, 0xd3, 0xd7, - 0xd3, 0xa8, 0xcd, 0xf9, 0x39, 0x39, 0x81, 0xd1, 0x8a, 0xb4, 0x8b, 0x0a, 0x96, 0x91, 0xdb, 0xd2, - 0x48, 0x2f, 0xb7, 0x71, 0xbe, 0x55, 0x8d, 0x56, 0xcb, 0xc3, 0x3b, 0x6b, 0x5f, 0xa3, 0xb5, 0xf2, - 0xf0, 0x96, 0xea, 0x7b, 0x74, 0xbb, 0xdc, 0xbe, 0xb9, 0xa2, 0x1d, 0xdd, 0x11, 0xa0, 0x42, 0x7c, - 0x16, 0xcb, 0x6d, 0xb4, 0x2e, 0x24, 0xba, 0x03, 0xcb, 0xb9, 0xf8, 0x2c, 0x3e, 0x65, 0xa2, 0x8d, - 0x14, 0x78, 0xa5, 0x1c, 0x48, 0xa5, 0xbf, 0x2b, 0x39, 0xed, 0x76, 0xc1, 0x12, 0xb9, 0x56, 0x0d, - 0xba, 0x27, 0xed, 0x30, 0x2d, 0x1f, 0xb2, 0x6c, 0xfe, 0xad, 0xa5, 0xfa, 0x77, 0x7c, 0xbe, 0x60, - 0xd1, 0x7c, 0x07, 0x1f, 0xbd, 0x5d, 0x6e, 0x2f, 0xa9, 0x15, 0x8d, 0xfa, 0xe5, 0x99, 0x5b, 0x34, - 0xa5, 0xd1, 0xfd, 0x72, 0x4b, 0x15, 0x9b, 0x50, 0xe8, 0x9d, 0x74, 0x27, 0x17, 0x3c, 0x2c, 0x77, - 0x0d, 0xd1, 0xbb, 0xa9, 0x5e, 0xeb, 0x79, 0x7e, 0xc5, 0xae, 0x25, 0xda, 0x4c, 0x35, 0x2c, 0x70, - 0xcc, 0xf7, 0x21, 0xd1, 0x7b, 0xb3, 0x38, 0x16, 0x9b, 0x87, 0xe8, 0xfd, 0x94, 0xa3, 0x5e, 0xcc, - 0x6d, 0xd9, 0xbd, 0x08, 0x7d, 0x50, 0x1e, 0xa9, 0xf9, 0x0b, 0x08, 0xfa, 0x50, 0x68, 0x5b, 0xb0, - 0xab, 0xf4, 0xef, 0x46, 0xe8, 0x9f, 0x05, 0xa3, 0x75, 0xb8, 0x9e, 0x53, 0xf4, 0xcc, 0x43, 0x25, - 0xfa, 0x48, 0x20, 0x6f, 0xe5, 0x8f, 0xa1, 0xc2, 0xbb, 0x22, 0xfa, 0x17, 0xb1, 0x66, 0x71, 0x0f, - 0xe5, 0x9a, 0x17, 0xe8, 0x41, 0x7a, 0x4c, 0x2e, 0x97, 0xa1, 0xb2, 0x9c, 0xf8, 0xaf, 0x69, 0x8a, - 0xb9, 0x52, 0x0e, 0xa4, 0xde, 0xff, 0xb7, 0x72, 0x6e, 0x67, 0x2e, 0x49, 0xe8, 0xe3, 0x19, 0x1b, - 0x3c, 0x8f, 0xfa, 0xa4, 0x7c, 0xcd, 0xdc, 0x75, 0x05, 0x7d, 0x2a, 0x58, 0x6d, 0xc0, 0x8d, 0x59, - 0x7a, 0x26, 0x2e, 0xfd, 0x4c, 0x40, 0xef, 0xc1, 0xcd, 0x32, 0x68, 0x7e, 0xcf, 0x6f, 0x09, 0x70, - 0x1f, 0xd6, 0xca, 0xc0, 0x67, 0xf6, 0xfe, 0x43, 0x21, 0xec, 0xbd, 0xbc, 0xee, 0x67, 0xee, 0x15, - 0xc8, 0x59, 0x6a, 0x7e, 0x9f, 0x6c, 0xeb, 0x3b, 0x33, 0xc0, 0xc9, 0xc5, 0x02, 0xe1, 0xa5, 0xda, - 0xf7, 0x25, 0x86, 0xca, 0xdf, 0x35, 0xd0, 0xd1, 0x52, 0xed, 0x87, 0x12, 0x43, 0xe5, 0xaa, 0x65, - 0x34, 0x14, 0xac, 0x0a, 0xe1, 0x2c, 0x57, 0xd0, 0x68, 0x24, 0x18, 0x15, 0x8c, 0x59, 0x52, 0x13, - 0x23, 0x57, 0xb0, 0x2b, 0x84, 0x61, 0x01, 0x8a, 0x3c, 0xc1, 0xf1, 0x2e, 0xac, 0x9c, 0x03, 0x63, - 0x15, 0x2f, 0xf2, 0x05, 0xcb, 0x59, 0xab, 0x67, 0xd5, 0x2b, 0xfa, 0x9a, 0x43, 0x1f, 0xbe, 0x0f, - 0xab, 0xb6, 0x37, 0xe9, 0x87, 0x56, 0xe4, 0x85, 0x23, 0x32, 0xb6, 0x0e, 0xc3, 0x7e, 0x14, 0xe0, - 0x97, 0x5e, 0xd0, 0x1f, 0x93, 0x43, 0xfe, 0x6f, 0x7e, 0x87, 0xf1, 0xd1, 0xc3, 0xce, 0x01, 0x23, - 0x0a, 0xae, 0x7f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xe4, 0xc0, 0x85, 0x16, 0x28, 0x00, 0x00, -} 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 deleted file mode 100644 index 8cb9c8cc2..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.proto +++ /dev/null @@ -1,905 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto -// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b. - -syntax = "proto2"; - -/** - * Messages for TREZOR communication - */ - -// Sugar for easier handling in Java -option java_package = "com.satoshilabs.trezor.lib.protobuf"; -option java_outer_classname = "TrezorMessage"; - -import "types.proto"; - -/** - * Mapping between Trezor wire identifier (uint) and a protobuf message - */ -enum MessageType { - MessageType_Initialize = 0 [(wire_in) = true]; - MessageType_Ping = 1 [(wire_in) = true]; - MessageType_Success = 2 [(wire_out) = true]; - MessageType_Failure = 3 [(wire_out) = true]; - MessageType_ChangePin = 4 [(wire_in) = true]; - MessageType_WipeDevice = 5 [(wire_in) = true]; - MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true]; - MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true]; - MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true]; - MessageType_GetEntropy = 9 [(wire_in) = true]; - MessageType_Entropy = 10 [(wire_out) = true]; - MessageType_GetPublicKey = 11 [(wire_in) = true]; - MessageType_PublicKey = 12 [(wire_out) = true]; - MessageType_LoadDevice = 13 [(wire_in) = true]; - MessageType_ResetDevice = 14 [(wire_in) = true]; - MessageType_SignTx = 15 [(wire_in) = true]; - MessageType_SimpleSignTx = 16 [(wire_in) = true, deprecated = true]; - MessageType_Features = 17 [(wire_out) = true]; - MessageType_PinMatrixRequest = 18 [(wire_out) = true]; - MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true]; - MessageType_Cancel = 20 [(wire_in) = true]; - MessageType_TxRequest = 21 [(wire_out) = true]; - MessageType_TxAck = 22 [(wire_in) = true]; - MessageType_CipherKeyValue = 23 [(wire_in) = true]; - MessageType_ClearSession = 24 [(wire_in) = true]; - MessageType_ApplySettings = 25 [(wire_in) = true]; - MessageType_ButtonRequest = 26 [(wire_out) = true]; - MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true]; - MessageType_ApplyFlags = 28 [(wire_in) = true]; - MessageType_GetAddress = 29 [(wire_in) = true]; - MessageType_Address = 30 [(wire_out) = true]; - MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true]; - MessageType_BackupDevice = 34 [(wire_in) = true]; - MessageType_EntropyRequest = 35 [(wire_out) = true]; - MessageType_EntropyAck = 36 [(wire_in) = true]; - MessageType_SignMessage = 38 [(wire_in) = true]; - MessageType_VerifyMessage = 39 [(wire_in) = true]; - MessageType_MessageSignature = 40 [(wire_out) = true]; - MessageType_PassphraseRequest = 41 [(wire_out) = true]; - MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true]; - MessageType_EstimateTxSize = 43 [(wire_in) = true, deprecated = true]; - MessageType_TxSize = 44 [(wire_out) = true, deprecated = true]; - MessageType_RecoveryDevice = 45 [(wire_in) = true]; - MessageType_WordRequest = 46 [(wire_out) = true]; - MessageType_WordAck = 47 [(wire_in) = true]; - MessageType_CipheredKeyValue = 48 [(wire_out) = true]; - MessageType_EncryptMessage = 49 [(wire_in) = true, deprecated = true]; - MessageType_EncryptedMessage = 50 [(wire_out) = true, deprecated = true]; - MessageType_DecryptMessage = 51 [(wire_in) = true, deprecated = true]; - MessageType_DecryptedMessage = 52 [(wire_out) = true, deprecated = true]; - MessageType_SignIdentity = 53 [(wire_in) = true]; - MessageType_SignedIdentity = 54 [(wire_out) = true]; - MessageType_GetFeatures = 55 [(wire_in) = true]; - MessageType_EthereumGetAddress = 56 [(wire_in) = true]; - MessageType_EthereumAddress = 57 [(wire_out) = true]; - MessageType_EthereumSignTx = 58 [(wire_in) = true]; - MessageType_EthereumTxRequest = 59 [(wire_out) = true]; - MessageType_EthereumTxAck = 60 [(wire_in) = true]; - MessageType_GetECDHSessionKey = 61 [(wire_in) = true]; - MessageType_ECDHSessionKey = 62 [(wire_out) = true]; - MessageType_SetU2FCounter = 63 [(wire_in) = true]; - MessageType_EthereumSignMessage = 64 [(wire_in) = true]; - MessageType_EthereumVerifyMessage = 65 [(wire_in) = true]; - MessageType_EthereumMessageSignature = 66 [(wire_out) = true]; - MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true]; - MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true]; - MessageType_DebugLinkState = 102 [(wire_debug_out) = true]; - MessageType_DebugLinkStop = 103 [(wire_debug_in) = true]; - MessageType_DebugLinkLog = 104 [(wire_debug_out) = true]; - MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true]; - MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true]; - MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true]; - MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true]; -} - -//////////////////// -// Basic messages // -//////////////////// - -/** - * Request: Reset device to default state and ask for device details - * @next Features - */ -message Initialize { -} - -/** - * Request: Ask for device details (no device reset) - * @next Features - */ -message GetFeatures { -} - -/** - * Response: Reports various information about the device - * @prev Initialize - * @prev GetFeatures - */ -message Features { - optional string vendor = 1; // name of the manufacturer, e.g. "bitcointrezor.com" - optional uint32 major_version = 2; // major version of the device, e.g. 1 - optional uint32 minor_version = 3; // minor version of the device, e.g. 0 - optional uint32 patch_version = 4; // patch version of the device, e.g. 0 - optional bool bootloader_mode = 5; // is device in bootloader mode? - optional string device_id = 6; // device's unique identifier - optional bool pin_protection = 7; // is device protected by PIN? - optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase? - optional string language = 9; // device language - optional string label = 10; // device description label - repeated CoinType coins = 11; // supported coins - optional bool initialized = 12; // does device contain seed? - optional bytes revision = 13; // SCM revision of firmware - optional bytes bootloader_hash = 14; // hash of the bootloader - optional bool imported = 15; // was storage imported from an external source? - optional bool pin_cached = 16; // is PIN already cached in session? - optional bool passphrase_cached = 17; // is passphrase already cached in session? - optional bool firmware_present = 18; // is valid firmware loaded? - optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup) - optional uint32 flags = 20; // device flags (equals to Storage.flags) -} - -/** - * Request: clear session (removes cached PIN, passphrase, etc). - * @next Success - */ -message ClearSession { -} - -/** - * Request: change language and/or label of the device - * @next Success - * @next Failure - * @next ButtonRequest - * @next PinMatrixRequest - */ -message ApplySettings { - optional string language = 1; - optional string label = 2; - optional bool use_passphrase = 3; - optional bytes homescreen = 4; -} - -/** - * Request: set flags of the device - * @next Success - * @next Failure - */ -message ApplyFlags { - optional uint32 flags = 1; // bitmask, can only set bits, not unset -} - -/** - * Request: Starts workflow for setting/changing/removing the PIN - * @next ButtonRequest - * @next PinMatrixRequest - */ -message ChangePin { - optional bool remove = 1; // is PIN removal requested? -} - -/** - * Request: Test if the device is alive, device sends back the message in Success response - * @next Success - */ -message Ping { - optional string message = 1; // message to send back in Success message - optional bool button_protection = 2; // ask for button press - optional bool pin_protection = 3; // ask for PIN if set in device - optional bool passphrase_protection = 4; // ask for passphrase if set in device -} - -/** - * Response: Success of the previous request - */ -message Success { - optional string message = 1; // human readable description of action or request-specific payload -} - -/** - * Response: Failure of the previous request - */ -message Failure { - optional FailureType code = 1; // computer-readable definition of the error state - optional string message = 2; // human-readable message of the error state -} - -/** - * Response: Device is waiting for HW button press. - * @next ButtonAck - * @next Cancel - */ -message ButtonRequest { - optional ButtonRequestType code = 1; - optional string data = 2; -} - -/** - * Request: Computer agrees to wait for HW button press - * @prev ButtonRequest - */ -message ButtonAck { -} - -/** - * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme - * @next PinMatrixAck - * @next Cancel - */ -message PinMatrixRequest { - optional PinMatrixRequestType type = 1; -} - -/** - * Request: Computer responds with encoded PIN - * @prev PinMatrixRequest - */ -message PinMatrixAck { - required string pin = 1; // matrix encoded PIN entered by user -} - -/** - * Request: Abort last operation that required user interaction - * @prev ButtonRequest - * @prev PinMatrixRequest - * @prev PassphraseRequest - */ -message Cancel { -} - -/** - * Response: Device awaits encryption passphrase - * @next PassphraseAck - * @next Cancel - */ -message PassphraseRequest { -} - -/** - * Request: Send passphrase back - * @prev PassphraseRequest - */ -message PassphraseAck { - required string passphrase = 1; -} - -/** - * Request: Request a sample of random data generated by hardware RNG. May be used for testing. - * @next ButtonRequest - * @next Entropy - * @next Failure - */ -message GetEntropy { - required uint32 size = 1; // size of requested entropy -} - -/** - * Response: Reply with random data generated by internal RNG - * @prev GetEntropy - */ -message Entropy { - required bytes entropy = 1; // stream of random generated bytes -} - -/** - * Request: Ask device for public key corresponding to address_n path - * @next PassphraseRequest - * @next PublicKey - * @next Failure - */ -message GetPublicKey { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional string ecdsa_curve_name = 2; // ECDSA curve name to use - optional bool show_display = 3; // optionally show on display before sending the result - optional string coin_name = 4 [default='Bitcoin']; -} - -/** - * Response: Contains public key derived from device private seed - * @prev GetPublicKey - */ -message PublicKey { - required HDNodeType node = 1; // BIP32 public node - optional string xpub = 2; // serialized form of public node -} - -/** - * Request: Ask device for address corresponding to address_n path - * @next PassphraseRequest - * @next Address - * @next Failure - */ -message GetAddress { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional string coin_name = 2 [default='Bitcoin']; - optional bool show_display = 3 ; // optionally show on display before sending the result - optional MultisigRedeemScriptType multisig = 4; // filled if we are showing a multisig address - optional InputScriptType script_type = 5 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) -} - -/** - * Request: Ask device for Ethereum address corresponding to address_n path - * @next PassphraseRequest - * @next EthereumAddress - * @next Failure - */ -message EthereumGetAddress { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bool show_display = 2; // optionally show on display before sending the result -} - -/** - * Response: Contains address derived from device private seed - * @prev GetAddress - */ -message Address { - required string address = 1; // Coin address in Base58 encoding -} - -/** - * Response: Contains an Ethereum address derived from device private seed - * @prev EthereumGetAddress - */ -message EthereumAddress { - required bytes address = 1; // Coin address as an Ethereum 160 bit hash -} - -/** - * Request: Request device to wipe all sensitive data and settings - * @next ButtonRequest - */ -message WipeDevice { -} - -/** - * Request: Load seed and related internal settings from the computer - * @next ButtonRequest - * @next Success - * @next Failure - */ -message LoadDevice { - optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words) - optional HDNodeType node = 2; // BIP-32 node - optional string pin = 3; // set PIN protection - optional bool passphrase_protection = 4; // enable master node encryption using passphrase - optional string language = 5 [default='english']; // device language - optional string label = 6; // device label - optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum - optional uint32 u2f_counter = 8; // U2F counter -} - -/** - * Request: Ask device to do initialization involving user interaction - * @next EntropyRequest - * @next Failure - */ -message ResetDevice { - optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy - optional uint32 strength = 2 [default=256]; // strength of seed in bits - optional bool passphrase_protection = 3; // enable master node encryption using passphrase - optional bool pin_protection = 4; // enable PIN protection - optional string language = 5 [default='english']; // device language - optional string label = 6; // device label - optional uint32 u2f_counter = 7; // U2F counter - optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow -} - -/** - * Request: Perform backup of the device seed if not backed up using ResetDevice - * @next ButtonRequest - */ -message BackupDevice { -} - -/** - * Response: Ask for additional entropy from host computer - * @prev ResetDevice - * @next EntropyAck - */ -message EntropyRequest { -} - -/** - * Request: Provide additional entropy for seed generation function - * @prev EntropyRequest - * @next ButtonRequest - */ -message EntropyAck { - optional bytes entropy = 1; // 256 bits (32 bytes) of random data -} - -/** - * Request: Start recovery workflow asking user for specific words of mnemonic - * Used to recovery device safely even on untrusted computer. - * @next WordRequest - */ -message RecoveryDevice { - optional uint32 word_count = 1; // number of words in BIP-39 mnemonic - optional bool passphrase_protection = 2; // enable master node encryption using passphrase - optional bool pin_protection = 3; // enable PIN protection - optional string language = 4 [default='english']; // device language - optional string label = 5; // device label - optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process - // 7 reserved for unused recovery method - optional uint32 type = 8; // supported recovery type (see RecoveryType) - optional uint32 u2f_counter = 9; // U2F counter - optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation) -} - -/** - * Response: Device is waiting for user to enter word of the mnemonic - * Its position is shown only on device's internal display. - * @prev RecoveryDevice - * @prev WordAck - */ -message WordRequest { - optional WordRequestType type = 1; -} - -/** - * Request: Computer replies with word from the mnemonic - * @prev WordRequest - * @next WordRequest - * @next Success - * @next Failure - */ -message WordAck { - required string word = 1; // one word of mnemonic on asked position -} - -////////////////////////////// -// Message signing messages // -////////////////////////////// - -/** - * Request: Ask device to sign message - * @next MessageSignature - * @next Failure - */ -message SignMessage { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - required bytes message = 2; // message to be signed - optional string coin_name = 3 [default='Bitcoin']; // coin to use for signing - optional InputScriptType script_type = 4 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) -} - -/** - * Request: Ask device to verify message - * @next Success - * @next Failure - */ -message VerifyMessage { - optional string address = 1; // address to verify - optional bytes signature = 2; // signature to verify - optional bytes message = 3; // message to verify - optional string coin_name = 4 [default='Bitcoin']; // coin to use for verifying -} - -/** - * Response: Signed message - * @prev SignMessage - */ -message MessageSignature { - optional string address = 1; // address used to sign the message - optional bytes signature = 2; // signature of the message -} - -/////////////////////////// -// Encryption/decryption // -/////////////////////////// - -/** - * Request: Ask device to encrypt message - * @next EncryptedMessage - * @next Failure - */ -message EncryptMessage { - optional bytes pubkey = 1; // public key - optional bytes message = 2; // message to encrypt - optional bool display_only = 3; // show just on display? (don't send back via wire) - repeated uint32 address_n = 4; // BIP-32 path to derive the signing key from master node - optional string coin_name = 5 [default='Bitcoin']; // coin to use for signing -} - -/** - * Response: Encrypted message - * @prev EncryptMessage - */ -message EncryptedMessage { - optional bytes nonce = 1; // nonce used during encryption - optional bytes message = 2; // encrypted message - optional bytes hmac = 3; // message hmac -} - -/** - * Request: Ask device to decrypt message - * @next Success - * @next Failure - */ -message DecryptMessage { - repeated uint32 address_n = 1; // BIP-32 path to derive the decryption key from master node - optional bytes nonce = 2; // nonce used during encryption - optional bytes message = 3; // message to decrypt - optional bytes hmac = 4; // message hmac -} - -/** - * Response: Decrypted message - * @prev DecryptedMessage - */ -message DecryptedMessage { - optional bytes message = 1; // decrypted message - optional string address = 2; // address used to sign the message (if used) -} - -/** - * Request: Ask device to encrypt or decrypt value of given key - * @next CipheredKeyValue - * @next Failure - */ -message CipherKeyValue { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional string key = 2; // key component of key:value - optional bytes value = 3; // value component of key:value - optional bool encrypt = 4; // are we encrypting (True) or decrypting (False)? - optional bool ask_on_encrypt = 5; // should we ask on encrypt operation? - optional bool ask_on_decrypt = 6; // should we ask on decrypt operation? - optional bytes iv = 7; // initialization vector (will be computed if not set) -} - -/** - * Response: Return ciphered/deciphered value - * @prev CipherKeyValue - */ -message CipheredKeyValue { - optional bytes value = 1; // ciphered/deciphered value -} - -////////////////////////////////// -// Transaction signing messages // -////////////////////////////////// - -/** - * Request: Estimated size of the transaction - * This behaves exactly like SignTx, which means that it can ask using TxRequest - * This call is non-blocking (except possible PassphraseRequest to unlock the seed) - * @next TxSize - * @next Failure - */ -message EstimateTxSize { - required uint32 outputs_count = 1; // number of transaction outputs - required uint32 inputs_count = 2; // number of transaction inputs - optional string coin_name = 3 [default='Bitcoin']; // coin to use -} - -/** - * Response: Estimated size of the transaction - * @prev EstimateTxSize - */ -message TxSize { - optional uint32 tx_size = 1; // estimated size of transaction in bytes -} - -/** - * Request: Ask device to sign transaction - * @next PassphraseRequest - * @next PinMatrixRequest - * @next TxRequest - * @next Failure - */ -message SignTx { - required uint32 outputs_count = 1; // number of transaction outputs - required uint32 inputs_count = 2; // number of transaction inputs - optional string coin_name = 3 [default='Bitcoin']; // coin to use - optional uint32 version = 4 [default=1]; // transaction version - optional uint32 lock_time = 5 [default=0]; // transaction lock_time -} - -/** - * Request: Simplified transaction signing - * This method doesn't support streaming, so there are hardware limits in number of inputs and outputs. - * In case of success, the result is returned using TxRequest message. - * @next PassphraseRequest - * @next PinMatrixRequest - * @next TxRequest - * @next Failure - */ -message SimpleSignTx { - repeated TxInputType inputs = 1; // transaction inputs - repeated TxOutputType outputs = 2; // transaction outputs - repeated TransactionType transactions = 3; // transactions whose outputs are used to build current inputs - optional string coin_name = 4 [default='Bitcoin']; // coin to use - optional uint32 version = 5 [default=1]; // transaction version - optional uint32 lock_time = 6 [default=0]; // transaction lock_time -} - -/** - * Response: Device asks for information for signing transaction or returns the last result - * If request_index is set, device awaits TxAck message (with fields filled in according to request_type) - * If signature_index is set, 'signature' contains signed input of signature_index's input - * @prev SignTx - * @prev SimpleSignTx - * @prev TxAck - */ -message TxRequest { - optional RequestType request_type = 1; // what should be filled in TxAck message? - optional TxRequestDetailsType details = 2; // request for tx details - optional TxRequestSerializedType serialized = 3; // serialized data and request for next -} - -/** - * Request: Reported transaction data - * @prev TxRequest - * @next TxRequest - */ -message TxAck { - optional TransactionType tx = 1; -} - -/** - * Request: Ask device to sign transaction - * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. - * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. - * @next PassphraseRequest - * @next PinMatrixRequest - * @next EthereumTxRequest - * @next Failure - */ -message EthereumSignTx { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bytes nonce = 2; // <=256 bit unsigned big endian - optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) - optional bytes gas_limit = 4; // <=256 bit unsigned big endian - optional bytes to = 5; // 160 bit address hash - optional bytes value = 6; // <=256 bit unsigned big endian (in wei) - optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) - optional uint32 data_length = 8; // Length of transaction payload - optional uint32 chain_id = 9; // Chain Id for EIP 155 -} - -/** - * Response: Device asks for more data from transaction payload, or returns the signature. - * If data_length is set, device awaits that many more bytes of payload. - * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. - * @prev EthereumSignTx - * @next EthereumTxAck - */ -message EthereumTxRequest { - optional uint32 data_length = 1; // Number of bytes being requested (<= 1024) - optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28) - optional bytes signature_r = 3; // Computed signature R component (256 bit) - optional bytes signature_s = 4; // Computed signature S component (256 bit) -} - -/** - * Request: Transaction payload data. - * @prev EthereumTxRequest - * @next EthereumTxRequest - */ -message EthereumTxAck { - optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) -} - -//////////////////////////////////////// -// Ethereum: Message signing messages // -//////////////////////////////////////// - -/** - * Request: Ask device to sign message - * @next EthereumMessageSignature - * @next Failure - */ -message EthereumSignMessage { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - required bytes message = 2; // message to be signed -} - -/** - * Request: Ask device to verify message - * @next Success - * @next Failure - */ -message EthereumVerifyMessage { - optional bytes address = 1; // address to verify - optional bytes signature = 2; // signature to verify - optional bytes message = 3; // message to verify -} - -/** - * Response: Signed message - * @prev EthereumSignMessage - */ -message EthereumMessageSignature { - optional bytes address = 1; // address used to sign the message - optional bytes signature = 2; // signature of the message -} - -/////////////////////// -// Identity messages // -/////////////////////// - -/** - * Request: Ask device to sign identity - * @next SignedIdentity - * @next Failure - */ -message SignIdentity { - optional IdentityType identity = 1; // identity - optional bytes challenge_hidden = 2; // non-visible challenge - optional string challenge_visual = 3; // challenge shown on display (e.g. date+time) - optional string ecdsa_curve_name = 4; // ECDSA curve name to use -} - -/** - * Response: Device provides signed identity - * @prev SignIdentity - */ -message SignedIdentity { - optional string address = 1; // identity address - optional bytes public_key = 2; // identity public key - optional bytes signature = 3; // signature of the identity data -} - -/////////////////// -// ECDH messages // -/////////////////// - -/** - * Request: Ask device to generate ECDH session key - * @next ECDHSessionKey - * @next Failure - */ -message GetECDHSessionKey { - optional IdentityType identity = 1; // identity - optional bytes peer_public_key = 2; // peer's public key - optional string ecdsa_curve_name = 3; // ECDSA curve name to use -} - -/** - * Response: Device provides ECDH session key - * @prev GetECDHSessionKey - */ -message ECDHSessionKey { - optional bytes session_key = 1; // ECDH session key -} - -/////////////////// -// U2F messages // -/////////////////// - -/** - * Request: Set U2F counter - * @next Success - */ -message SetU2FCounter { - optional uint32 u2f_counter = 1; // counter -} - -///////////////////////// -// Bootloader messages // -///////////////////////// - -/** - * Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload) - * @next Success - * @next FirmwareRequest - * @next Failure - */ -message FirmwareErase { - optional uint32 length = 1; // length of new firmware -} - -/** - * Response: Ask for firmware chunk - * @next FirmwareUpload - */ -message FirmwareRequest { - optional uint32 offset = 1; // offset of requested firmware chunk - optional uint32 length = 2; // length of requested firmware chunk -} - -/** - * Request: Send firmware in binary form to the device - * @next Success - * @next Failure - */ -message FirmwareUpload { - required bytes payload = 1; // firmware to be loaded into device - optional bytes hash = 2; // hash of the payload -} - - -/** - * Request: Perform a device self-test - * @next Success - * @next Failure - */ -message SelfTest { - optional bytes payload = 1; // payload to be used in self-test -} - -///////////////////////////////////////////////////////////// -// Debug messages (only available if DebugLink is enabled) // -///////////////////////////////////////////////////////////// - -/** - * Request: "Press" the button on the device - * @next Success - */ -message DebugLinkDecision { - required bool yes_no = 1; // true for "Confirm", false for "Cancel" -} - -/** - * Request: Computer asks for device state - * @next DebugLinkState - */ -message DebugLinkGetState { -} - -/** - * Response: Device current state - * @prev DebugLinkGetState - */ -message DebugLinkState { - optional bytes layout = 1; // raw buffer of display - optional string pin = 2; // current PIN, blank if PIN is not set/enabled - optional string matrix = 3; // current PIN matrix - optional string mnemonic = 4; // current BIP-39 mnemonic - optional HDNodeType node = 5; // current BIP-32 node - optional bool passphrase_protection = 6; // is node/mnemonic encrypted using passphrase? - optional string reset_word = 7; // word on device display during ResetDevice workflow - optional bytes reset_entropy = 8; // current entropy during ResetDevice workflow - optional string recovery_fake_word = 9; // (fake) word on display during RecoveryDevice workflow - optional uint32 recovery_word_pos = 10; // index of mnemonic word the device is expecting during RecoveryDevice workflow -} - -/** - * Request: Ask device to restart - */ -message DebugLinkStop { -} - -/** - * Response: Device wants host to log event - */ -message DebugLinkLog { - optional uint32 level = 1; - optional string bucket = 2; - optional string text = 3; -} - -/** - * Request: Read memory from device - * @next DebugLinkMemory - */ -message DebugLinkMemoryRead { - optional uint32 address = 1; - optional uint32 length = 2; -} - -/** - * Response: Device sends memory back - * @prev DebugLinkMemoryRead - */ -message DebugLinkMemory { - optional bytes memory = 1; -} - -/** - * Request: Write memory to device. - * WARNING: Writing to the wrong location can irreparably break the device. - */ -message DebugLinkMemoryWrite { - optional uint32 address = 1; - optional bytes memory = 2; - optional bool flash = 3; -} - -/** - * Request: Erase block of flash on device - * WARNING: Writing to the wrong location can irreparably break the device. - */ -message DebugLinkFlashErase { - optional uint32 sector = 1; -} 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 deleted file mode 100644 index 80cc75efc..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/trezor.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// This file contains the implementation for interacting with the Trezor hardware -// 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=import_path=trezor:. types.proto messages.proto - -// Package trezor contains the wire protocol wrapper in Go. -package trezor - -import ( - "reflect" - - "github.com/golang/protobuf/proto" -) - -// Type returns the protocol buffer type number of a specific message. If the -// message is nil, this method panics! -func Type(msg proto.Message) uint16 { - return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()]) -} - -// Name returns the friendly message type name of a specific protocol buffer -// type number. -func Name(kind uint16) string { - name := MessageType_name[int32(kind)] - if len(name) < 12 { - return name - } - return name[12:] -} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.pb.go deleted file mode 100644 index 25b7672d2..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.pb.go +++ /dev/null @@ -1,1333 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: types.proto - -/* -Package trezor is a generated protocol buffer package. - -It is generated from these files: - types.proto - messages.proto - -It has these top-level messages: - HDNodeType - HDNodePathType - CoinType - MultisigRedeemScriptType - TxInputType - TxOutputType - TxOutputBinType - TransactionType - TxRequestDetailsType - TxRequestSerializedType - IdentityType - Initialize - GetFeatures - Features - ClearSession - ApplySettings - ApplyFlags - ChangePin - Ping - Success - Failure - ButtonRequest - ButtonAck - PinMatrixRequest - PinMatrixAck - Cancel - PassphraseRequest - PassphraseAck - GetEntropy - Entropy - GetPublicKey - PublicKey - GetAddress - EthereumGetAddress - Address - EthereumAddress - WipeDevice - LoadDevice - ResetDevice - BackupDevice - EntropyRequest - EntropyAck - RecoveryDevice - WordRequest - WordAck - SignMessage - VerifyMessage - MessageSignature - EncryptMessage - EncryptedMessage - DecryptMessage - DecryptedMessage - CipherKeyValue - CipheredKeyValue - EstimateTxSize - TxSize - SignTx - SimpleSignTx - TxRequest - TxAck - EthereumSignTx - EthereumTxRequest - EthereumTxAck - EthereumSignMessage - EthereumVerifyMessage - EthereumMessageSignature - SignIdentity - SignedIdentity - GetECDHSessionKey - ECDHSessionKey - SetU2FCounter - FirmwareErase - FirmwareRequest - FirmwareUpload - SelfTest - DebugLinkDecision - DebugLinkGetState - DebugLinkState - DebugLinkStop - DebugLinkLog - DebugLinkMemoryRead - DebugLinkMemory - DebugLinkMemoryWrite - DebugLinkFlashErase -*/ -package trezor - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" -import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -// * -// Type of failures returned by Failure message -// @used_in Failure -type FailureType int32 - -const ( - FailureType_Failure_UnexpectedMessage FailureType = 1 - FailureType_Failure_ButtonExpected FailureType = 2 - FailureType_Failure_DataError FailureType = 3 - FailureType_Failure_ActionCancelled FailureType = 4 - FailureType_Failure_PinExpected FailureType = 5 - FailureType_Failure_PinCancelled FailureType = 6 - FailureType_Failure_PinInvalid FailureType = 7 - FailureType_Failure_InvalidSignature FailureType = 8 - FailureType_Failure_ProcessError FailureType = 9 - FailureType_Failure_NotEnoughFunds FailureType = 10 - FailureType_Failure_NotInitialized FailureType = 11 - FailureType_Failure_FirmwareError FailureType = 99 -) - -var FailureType_name = map[int32]string{ - 1: "Failure_UnexpectedMessage", - 2: "Failure_ButtonExpected", - 3: "Failure_DataError", - 4: "Failure_ActionCancelled", - 5: "Failure_PinExpected", - 6: "Failure_PinCancelled", - 7: "Failure_PinInvalid", - 8: "Failure_InvalidSignature", - 9: "Failure_ProcessError", - 10: "Failure_NotEnoughFunds", - 11: "Failure_NotInitialized", - 99: "Failure_FirmwareError", -} -var FailureType_value = map[string]int32{ - "Failure_UnexpectedMessage": 1, - "Failure_ButtonExpected": 2, - "Failure_DataError": 3, - "Failure_ActionCancelled": 4, - "Failure_PinExpected": 5, - "Failure_PinCancelled": 6, - "Failure_PinInvalid": 7, - "Failure_InvalidSignature": 8, - "Failure_ProcessError": 9, - "Failure_NotEnoughFunds": 10, - "Failure_NotInitialized": 11, - "Failure_FirmwareError": 99, -} - -func (x FailureType) Enum() *FailureType { - p := new(FailureType) - *p = x - return p -} -func (x FailureType) String() string { - return proto.EnumName(FailureType_name, int32(x)) -} -func (x *FailureType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(FailureType_value, data, "FailureType") - if err != nil { - return err - } - *x = FailureType(value) - return nil -} -func (FailureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -// * -// Type of script which will be used for transaction output -// @used_in TxOutputType -type OutputScriptType int32 - -const ( - OutputScriptType_PAYTOADDRESS OutputScriptType = 0 - OutputScriptType_PAYTOSCRIPTHASH OutputScriptType = 1 - OutputScriptType_PAYTOMULTISIG OutputScriptType = 2 - OutputScriptType_PAYTOOPRETURN OutputScriptType = 3 - OutputScriptType_PAYTOWITNESS OutputScriptType = 4 - OutputScriptType_PAYTOP2SHWITNESS OutputScriptType = 5 -) - -var OutputScriptType_name = map[int32]string{ - 0: "PAYTOADDRESS", - 1: "PAYTOSCRIPTHASH", - 2: "PAYTOMULTISIG", - 3: "PAYTOOPRETURN", - 4: "PAYTOWITNESS", - 5: "PAYTOP2SHWITNESS", -} -var OutputScriptType_value = map[string]int32{ - "PAYTOADDRESS": 0, - "PAYTOSCRIPTHASH": 1, - "PAYTOMULTISIG": 2, - "PAYTOOPRETURN": 3, - "PAYTOWITNESS": 4, - "PAYTOP2SHWITNESS": 5, -} - -func (x OutputScriptType) Enum() *OutputScriptType { - p := new(OutputScriptType) - *p = x - return p -} -func (x OutputScriptType) String() string { - return proto.EnumName(OutputScriptType_name, int32(x)) -} -func (x *OutputScriptType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(OutputScriptType_value, data, "OutputScriptType") - if err != nil { - return err - } - *x = OutputScriptType(value) - return nil -} -func (OutputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -// * -// Type of script which will be used for transaction output -// @used_in TxInputType -type InputScriptType int32 - -const ( - InputScriptType_SPENDADDRESS InputScriptType = 0 - InputScriptType_SPENDMULTISIG InputScriptType = 1 - InputScriptType_EXTERNAL InputScriptType = 2 - InputScriptType_SPENDWITNESS InputScriptType = 3 - InputScriptType_SPENDP2SHWITNESS InputScriptType = 4 -) - -var InputScriptType_name = map[int32]string{ - 0: "SPENDADDRESS", - 1: "SPENDMULTISIG", - 2: "EXTERNAL", - 3: "SPENDWITNESS", - 4: "SPENDP2SHWITNESS", -} -var InputScriptType_value = map[string]int32{ - "SPENDADDRESS": 0, - "SPENDMULTISIG": 1, - "EXTERNAL": 2, - "SPENDWITNESS": 3, - "SPENDP2SHWITNESS": 4, -} - -func (x InputScriptType) Enum() *InputScriptType { - p := new(InputScriptType) - *p = x - return p -} -func (x InputScriptType) String() string { - return proto.EnumName(InputScriptType_name, int32(x)) -} -func (x *InputScriptType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(InputScriptType_value, data, "InputScriptType") - if err != nil { - return err - } - *x = InputScriptType(value) - return nil -} -func (InputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -// * -// Type of information required by transaction signing process -// @used_in TxRequest -type RequestType int32 - -const ( - RequestType_TXINPUT RequestType = 0 - RequestType_TXOUTPUT RequestType = 1 - RequestType_TXMETA RequestType = 2 - RequestType_TXFINISHED RequestType = 3 - RequestType_TXEXTRADATA RequestType = 4 -) - -var RequestType_name = map[int32]string{ - 0: "TXINPUT", - 1: "TXOUTPUT", - 2: "TXMETA", - 3: "TXFINISHED", - 4: "TXEXTRADATA", -} -var RequestType_value = map[string]int32{ - "TXINPUT": 0, - "TXOUTPUT": 1, - "TXMETA": 2, - "TXFINISHED": 3, - "TXEXTRADATA": 4, -} - -func (x RequestType) Enum() *RequestType { - p := new(RequestType) - *p = x - return p -} -func (x RequestType) String() string { - return proto.EnumName(RequestType_name, int32(x)) -} -func (x *RequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RequestType_value, data, "RequestType") - if err != nil { - return err - } - *x = RequestType(value) - return nil -} -func (RequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -// * -// Type of button request -// @used_in ButtonRequest -type ButtonRequestType int32 - -const ( - ButtonRequestType_ButtonRequest_Other ButtonRequestType = 1 - ButtonRequestType_ButtonRequest_FeeOverThreshold ButtonRequestType = 2 - ButtonRequestType_ButtonRequest_ConfirmOutput ButtonRequestType = 3 - ButtonRequestType_ButtonRequest_ResetDevice ButtonRequestType = 4 - ButtonRequestType_ButtonRequest_ConfirmWord ButtonRequestType = 5 - ButtonRequestType_ButtonRequest_WipeDevice ButtonRequestType = 6 - ButtonRequestType_ButtonRequest_ProtectCall ButtonRequestType = 7 - ButtonRequestType_ButtonRequest_SignTx ButtonRequestType = 8 - ButtonRequestType_ButtonRequest_FirmwareCheck ButtonRequestType = 9 - ButtonRequestType_ButtonRequest_Address ButtonRequestType = 10 - ButtonRequestType_ButtonRequest_PublicKey ButtonRequestType = 11 -) - -var ButtonRequestType_name = map[int32]string{ - 1: "ButtonRequest_Other", - 2: "ButtonRequest_FeeOverThreshold", - 3: "ButtonRequest_ConfirmOutput", - 4: "ButtonRequest_ResetDevice", - 5: "ButtonRequest_ConfirmWord", - 6: "ButtonRequest_WipeDevice", - 7: "ButtonRequest_ProtectCall", - 8: "ButtonRequest_SignTx", - 9: "ButtonRequest_FirmwareCheck", - 10: "ButtonRequest_Address", - 11: "ButtonRequest_PublicKey", -} -var ButtonRequestType_value = map[string]int32{ - "ButtonRequest_Other": 1, - "ButtonRequest_FeeOverThreshold": 2, - "ButtonRequest_ConfirmOutput": 3, - "ButtonRequest_ResetDevice": 4, - "ButtonRequest_ConfirmWord": 5, - "ButtonRequest_WipeDevice": 6, - "ButtonRequest_ProtectCall": 7, - "ButtonRequest_SignTx": 8, - "ButtonRequest_FirmwareCheck": 9, - "ButtonRequest_Address": 10, - "ButtonRequest_PublicKey": 11, -} - -func (x ButtonRequestType) Enum() *ButtonRequestType { - p := new(ButtonRequestType) - *p = x - return p -} -func (x ButtonRequestType) String() string { - return proto.EnumName(ButtonRequestType_name, int32(x)) -} -func (x *ButtonRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ButtonRequestType_value, data, "ButtonRequestType") - if err != nil { - return err - } - *x = ButtonRequestType(value) - return nil -} -func (ButtonRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -// * -// Type of PIN request -// @used_in PinMatrixRequest -type PinMatrixRequestType int32 - -const ( - PinMatrixRequestType_PinMatrixRequestType_Current PinMatrixRequestType = 1 - PinMatrixRequestType_PinMatrixRequestType_NewFirst PinMatrixRequestType = 2 - PinMatrixRequestType_PinMatrixRequestType_NewSecond PinMatrixRequestType = 3 -) - -var PinMatrixRequestType_name = map[int32]string{ - 1: "PinMatrixRequestType_Current", - 2: "PinMatrixRequestType_NewFirst", - 3: "PinMatrixRequestType_NewSecond", -} -var PinMatrixRequestType_value = map[string]int32{ - "PinMatrixRequestType_Current": 1, - "PinMatrixRequestType_NewFirst": 2, - "PinMatrixRequestType_NewSecond": 3, -} - -func (x PinMatrixRequestType) Enum() *PinMatrixRequestType { - p := new(PinMatrixRequestType) - *p = x - return p -} -func (x PinMatrixRequestType) String() string { - return proto.EnumName(PinMatrixRequestType_name, int32(x)) -} -func (x *PinMatrixRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PinMatrixRequestType_value, data, "PinMatrixRequestType") - if err != nil { - return err - } - *x = PinMatrixRequestType(value) - return nil -} -func (PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -// * -// Type of recovery procedure. These should be used as bitmask, e.g., -// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` -// listing every method supported by the host computer. -// -// Note that ScrambledWords must be supported by every implementation -// for backward compatibility; there is no way to not support it. -// -// @used_in RecoveryDevice -type RecoveryDeviceType int32 - -const ( - // use powers of two when extending this field - RecoveryDeviceType_RecoveryDeviceType_ScrambledWords RecoveryDeviceType = 0 - RecoveryDeviceType_RecoveryDeviceType_Matrix RecoveryDeviceType = 1 -) - -var RecoveryDeviceType_name = map[int32]string{ - 0: "RecoveryDeviceType_ScrambledWords", - 1: "RecoveryDeviceType_Matrix", -} -var RecoveryDeviceType_value = map[string]int32{ - "RecoveryDeviceType_ScrambledWords": 0, - "RecoveryDeviceType_Matrix": 1, -} - -func (x RecoveryDeviceType) Enum() *RecoveryDeviceType { - p := new(RecoveryDeviceType) - *p = x - return p -} -func (x RecoveryDeviceType) String() string { - return proto.EnumName(RecoveryDeviceType_name, int32(x)) -} -func (x *RecoveryDeviceType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RecoveryDeviceType_value, data, "RecoveryDeviceType") - if err != nil { - return err - } - *x = RecoveryDeviceType(value) - return nil -} -func (RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } - -// * -// Type of Recovery Word request -// @used_in WordRequest -type WordRequestType int32 - -const ( - WordRequestType_WordRequestType_Plain WordRequestType = 0 - WordRequestType_WordRequestType_Matrix9 WordRequestType = 1 - WordRequestType_WordRequestType_Matrix6 WordRequestType = 2 -) - -var WordRequestType_name = map[int32]string{ - 0: "WordRequestType_Plain", - 1: "WordRequestType_Matrix9", - 2: "WordRequestType_Matrix6", -} -var WordRequestType_value = map[string]int32{ - "WordRequestType_Plain": 0, - "WordRequestType_Matrix9": 1, - "WordRequestType_Matrix6": 2, -} - -func (x WordRequestType) Enum() *WordRequestType { - p := new(WordRequestType) - *p = x - return p -} -func (x WordRequestType) String() string { - return proto.EnumName(WordRequestType_name, int32(x)) -} -func (x *WordRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(WordRequestType_value, data, "WordRequestType") - if err != nil { - return err - } - *x = WordRequestType(value) - return nil -} -func (WordRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } - -// * -// Structure representing BIP32 (hierarchical deterministic) node -// Used for imports of private key into the device and exporting public key out of device -// @used_in PublicKey -// @used_in LoadDevice -// @used_in DebugLinkState -// @used_in Storage -type HDNodeType struct { - Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"` - Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"` - ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"` - ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"` - PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"` - PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *HDNodeType) Reset() { *m = HDNodeType{} } -func (m *HDNodeType) String() string { return proto.CompactTextString(m) } -func (*HDNodeType) ProtoMessage() {} -func (*HDNodeType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *HDNodeType) GetDepth() uint32 { - if m != nil && m.Depth != nil { - return *m.Depth - } - return 0 -} - -func (m *HDNodeType) GetFingerprint() uint32 { - if m != nil && m.Fingerprint != nil { - return *m.Fingerprint - } - return 0 -} - -func (m *HDNodeType) GetChildNum() uint32 { - if m != nil && m.ChildNum != nil { - return *m.ChildNum - } - return 0 -} - -func (m *HDNodeType) GetChainCode() []byte { - if m != nil { - return m.ChainCode - } - return nil -} - -func (m *HDNodeType) GetPrivateKey() []byte { - if m != nil { - return m.PrivateKey - } - return nil -} - -func (m *HDNodeType) GetPublicKey() []byte { - if m != nil { - return m.PublicKey - } - return nil -} - -type HDNodePathType struct { - Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"` - AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *HDNodePathType) Reset() { *m = HDNodePathType{} } -func (m *HDNodePathType) String() string { return proto.CompactTextString(m) } -func (*HDNodePathType) ProtoMessage() {} -func (*HDNodePathType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -func (m *HDNodePathType) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *HDNodePathType) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -// * -// Structure representing Coin -// @used_in Features -type CoinType struct { - CoinName *string `protobuf:"bytes,1,opt,name=coin_name,json=coinName" json:"coin_name,omitempty"` - CoinShortcut *string `protobuf:"bytes,2,opt,name=coin_shortcut,json=coinShortcut" json:"coin_shortcut,omitempty"` - AddressType *uint32 `protobuf:"varint,3,opt,name=address_type,json=addressType,def=0" json:"address_type,omitempty"` - MaxfeeKb *uint64 `protobuf:"varint,4,opt,name=maxfee_kb,json=maxfeeKb" json:"maxfee_kb,omitempty"` - AddressTypeP2Sh *uint32 `protobuf:"varint,5,opt,name=address_type_p2sh,json=addressTypeP2sh,def=5" json:"address_type_p2sh,omitempty"` - SignedMessageHeader *string `protobuf:"bytes,8,opt,name=signed_message_header,json=signedMessageHeader" json:"signed_message_header,omitempty"` - XpubMagic *uint32 `protobuf:"varint,9,opt,name=xpub_magic,json=xpubMagic,def=76067358" json:"xpub_magic,omitempty"` - XprvMagic *uint32 `protobuf:"varint,10,opt,name=xprv_magic,json=xprvMagic,def=76066276" json:"xprv_magic,omitempty"` - Segwit *bool `protobuf:"varint,11,opt,name=segwit" json:"segwit,omitempty"` - Forkid *uint32 `protobuf:"varint,12,opt,name=forkid" json:"forkid,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CoinType) Reset() { *m = CoinType{} } -func (m *CoinType) String() string { return proto.CompactTextString(m) } -func (*CoinType) ProtoMessage() {} -func (*CoinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -const Default_CoinType_AddressType uint32 = 0 -const Default_CoinType_AddressTypeP2Sh uint32 = 5 -const Default_CoinType_XpubMagic uint32 = 76067358 -const Default_CoinType_XprvMagic uint32 = 76066276 - -func (m *CoinType) GetCoinName() string { - if m != nil && m.CoinName != nil { - return *m.CoinName - } - return "" -} - -func (m *CoinType) GetCoinShortcut() string { - if m != nil && m.CoinShortcut != nil { - return *m.CoinShortcut - } - return "" -} - -func (m *CoinType) GetAddressType() uint32 { - if m != nil && m.AddressType != nil { - return *m.AddressType - } - return Default_CoinType_AddressType -} - -func (m *CoinType) GetMaxfeeKb() uint64 { - if m != nil && m.MaxfeeKb != nil { - return *m.MaxfeeKb - } - return 0 -} - -func (m *CoinType) GetAddressTypeP2Sh() uint32 { - if m != nil && m.AddressTypeP2Sh != nil { - return *m.AddressTypeP2Sh - } - return Default_CoinType_AddressTypeP2Sh -} - -func (m *CoinType) GetSignedMessageHeader() string { - if m != nil && m.SignedMessageHeader != nil { - return *m.SignedMessageHeader - } - return "" -} - -func (m *CoinType) GetXpubMagic() uint32 { - if m != nil && m.XpubMagic != nil { - return *m.XpubMagic - } - return Default_CoinType_XpubMagic -} - -func (m *CoinType) GetXprvMagic() uint32 { - if m != nil && m.XprvMagic != nil { - return *m.XprvMagic - } - return Default_CoinType_XprvMagic -} - -func (m *CoinType) GetSegwit() bool { - if m != nil && m.Segwit != nil { - return *m.Segwit - } - return false -} - -func (m *CoinType) GetForkid() uint32 { - if m != nil && m.Forkid != nil { - return *m.Forkid - } - return 0 -} - -// * -// Type of redeem script used in input -// @used_in TxInputType -type MultisigRedeemScriptType struct { - Pubkeys []*HDNodePathType `protobuf:"bytes,1,rep,name=pubkeys" json:"pubkeys,omitempty"` - Signatures [][]byte `protobuf:"bytes,2,rep,name=signatures" json:"signatures,omitempty"` - M *uint32 `protobuf:"varint,3,opt,name=m" json:"m,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MultisigRedeemScriptType) Reset() { *m = MultisigRedeemScriptType{} } -func (m *MultisigRedeemScriptType) String() string { return proto.CompactTextString(m) } -func (*MultisigRedeemScriptType) ProtoMessage() {} -func (*MultisigRedeemScriptType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *MultisigRedeemScriptType) GetPubkeys() []*HDNodePathType { - if m != nil { - return m.Pubkeys - } - return nil -} - -func (m *MultisigRedeemScriptType) GetSignatures() [][]byte { - if m != nil { - return m.Signatures - } - return nil -} - -func (m *MultisigRedeemScriptType) GetM() uint32 { - if m != nil && m.M != nil { - return *m.M - } - return 0 -} - -// * -// Structure representing transaction input -// @used_in SimpleSignTx -// @used_in TransactionType -type TxInputType struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - PrevHash []byte `protobuf:"bytes,2,req,name=prev_hash,json=prevHash" json:"prev_hash,omitempty"` - PrevIndex *uint32 `protobuf:"varint,3,req,name=prev_index,json=prevIndex" json:"prev_index,omitempty"` - ScriptSig []byte `protobuf:"bytes,4,opt,name=script_sig,json=scriptSig" json:"script_sig,omitempty"` - Sequence *uint32 `protobuf:"varint,5,opt,name=sequence,def=4294967295" json:"sequence,omitempty"` - ScriptType *InputScriptType `protobuf:"varint,6,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"` - Multisig *MultisigRedeemScriptType `protobuf:"bytes,7,opt,name=multisig" json:"multisig,omitempty"` - Amount *uint64 `protobuf:"varint,8,opt,name=amount" json:"amount,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxInputType) Reset() { *m = TxInputType{} } -func (m *TxInputType) String() string { return proto.CompactTextString(m) } -func (*TxInputType) ProtoMessage() {} -func (*TxInputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -const Default_TxInputType_Sequence uint32 = 4294967295 -const Default_TxInputType_ScriptType InputScriptType = InputScriptType_SPENDADDRESS - -func (m *TxInputType) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *TxInputType) GetPrevHash() []byte { - if m != nil { - return m.PrevHash - } - return nil -} - -func (m *TxInputType) GetPrevIndex() uint32 { - if m != nil && m.PrevIndex != nil { - return *m.PrevIndex - } - return 0 -} - -func (m *TxInputType) GetScriptSig() []byte { - if m != nil { - return m.ScriptSig - } - return nil -} - -func (m *TxInputType) GetSequence() uint32 { - if m != nil && m.Sequence != nil { - return *m.Sequence - } - return Default_TxInputType_Sequence -} - -func (m *TxInputType) GetScriptType() InputScriptType { - if m != nil && m.ScriptType != nil { - return *m.ScriptType - } - return Default_TxInputType_ScriptType -} - -func (m *TxInputType) GetMultisig() *MultisigRedeemScriptType { - if m != nil { - return m.Multisig - } - return nil -} - -func (m *TxInputType) GetAmount() uint64 { - if m != nil && m.Amount != nil { - return *m.Amount - } - return 0 -} - -// * -// Structure representing transaction output -// @used_in SimpleSignTx -// @used_in TransactionType -type TxOutputType struct { - Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` - AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Amount *uint64 `protobuf:"varint,3,req,name=amount" json:"amount,omitempty"` - ScriptType *OutputScriptType `protobuf:"varint,4,req,name=script_type,json=scriptType,enum=OutputScriptType" json:"script_type,omitempty"` - Multisig *MultisigRedeemScriptType `protobuf:"bytes,5,opt,name=multisig" json:"multisig,omitempty"` - OpReturnData []byte `protobuf:"bytes,6,opt,name=op_return_data,json=opReturnData" json:"op_return_data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxOutputType) Reset() { *m = TxOutputType{} } -func (m *TxOutputType) String() string { return proto.CompactTextString(m) } -func (*TxOutputType) ProtoMessage() {} -func (*TxOutputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -func (m *TxOutputType) GetAddress() string { - if m != nil && m.Address != nil { - return *m.Address - } - return "" -} - -func (m *TxOutputType) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *TxOutputType) GetAmount() uint64 { - if m != nil && m.Amount != nil { - return *m.Amount - } - return 0 -} - -func (m *TxOutputType) GetScriptType() OutputScriptType { - if m != nil && m.ScriptType != nil { - return *m.ScriptType - } - return OutputScriptType_PAYTOADDRESS -} - -func (m *TxOutputType) GetMultisig() *MultisigRedeemScriptType { - if m != nil { - return m.Multisig - } - return nil -} - -func (m *TxOutputType) GetOpReturnData() []byte { - if m != nil { - return m.OpReturnData - } - return nil -} - -// * -// Structure representing compiled transaction output -// @used_in TransactionType -type TxOutputBinType struct { - Amount *uint64 `protobuf:"varint,1,req,name=amount" json:"amount,omitempty"` - ScriptPubkey []byte `protobuf:"bytes,2,req,name=script_pubkey,json=scriptPubkey" json:"script_pubkey,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxOutputBinType) Reset() { *m = TxOutputBinType{} } -func (m *TxOutputBinType) String() string { return proto.CompactTextString(m) } -func (*TxOutputBinType) ProtoMessage() {} -func (*TxOutputBinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } - -func (m *TxOutputBinType) GetAmount() uint64 { - if m != nil && m.Amount != nil { - return *m.Amount - } - return 0 -} - -func (m *TxOutputBinType) GetScriptPubkey() []byte { - if m != nil { - return m.ScriptPubkey - } - return nil -} - -// * -// Structure representing transaction -// @used_in SimpleSignTx -type TransactionType struct { - Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` - Inputs []*TxInputType `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"` - BinOutputs []*TxOutputBinType `protobuf:"bytes,3,rep,name=bin_outputs,json=binOutputs" json:"bin_outputs,omitempty"` - Outputs []*TxOutputType `protobuf:"bytes,5,rep,name=outputs" json:"outputs,omitempty"` - LockTime *uint32 `protobuf:"varint,4,opt,name=lock_time,json=lockTime" json:"lock_time,omitempty"` - InputsCnt *uint32 `protobuf:"varint,6,opt,name=inputs_cnt,json=inputsCnt" json:"inputs_cnt,omitempty"` - OutputsCnt *uint32 `protobuf:"varint,7,opt,name=outputs_cnt,json=outputsCnt" json:"outputs_cnt,omitempty"` - ExtraData []byte `protobuf:"bytes,8,opt,name=extra_data,json=extraData" json:"extra_data,omitempty"` - ExtraDataLen *uint32 `protobuf:"varint,9,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TransactionType) Reset() { *m = TransactionType{} } -func (m *TransactionType) String() string { return proto.CompactTextString(m) } -func (*TransactionType) ProtoMessage() {} -func (*TransactionType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } - -func (m *TransactionType) GetVersion() uint32 { - if m != nil && m.Version != nil { - return *m.Version - } - return 0 -} - -func (m *TransactionType) GetInputs() []*TxInputType { - if m != nil { - return m.Inputs - } - return nil -} - -func (m *TransactionType) GetBinOutputs() []*TxOutputBinType { - if m != nil { - return m.BinOutputs - } - return nil -} - -func (m *TransactionType) GetOutputs() []*TxOutputType { - if m != nil { - return m.Outputs - } - return nil -} - -func (m *TransactionType) GetLockTime() uint32 { - if m != nil && m.LockTime != nil { - return *m.LockTime - } - return 0 -} - -func (m *TransactionType) GetInputsCnt() uint32 { - if m != nil && m.InputsCnt != nil { - return *m.InputsCnt - } - return 0 -} - -func (m *TransactionType) GetOutputsCnt() uint32 { - if m != nil && m.OutputsCnt != nil { - return *m.OutputsCnt - } - return 0 -} - -func (m *TransactionType) GetExtraData() []byte { - if m != nil { - return m.ExtraData - } - return nil -} - -func (m *TransactionType) GetExtraDataLen() uint32 { - if m != nil && m.ExtraDataLen != nil { - return *m.ExtraDataLen - } - return 0 -} - -// * -// Structure representing request details -// @used_in TxRequest -type TxRequestDetailsType struct { - RequestIndex *uint32 `protobuf:"varint,1,opt,name=request_index,json=requestIndex" json:"request_index,omitempty"` - TxHash []byte `protobuf:"bytes,2,opt,name=tx_hash,json=txHash" json:"tx_hash,omitempty"` - ExtraDataLen *uint32 `protobuf:"varint,3,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"` - ExtraDataOffset *uint32 `protobuf:"varint,4,opt,name=extra_data_offset,json=extraDataOffset" json:"extra_data_offset,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxRequestDetailsType) Reset() { *m = TxRequestDetailsType{} } -func (m *TxRequestDetailsType) String() string { return proto.CompactTextString(m) } -func (*TxRequestDetailsType) ProtoMessage() {} -func (*TxRequestDetailsType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } - -func (m *TxRequestDetailsType) GetRequestIndex() uint32 { - if m != nil && m.RequestIndex != nil { - return *m.RequestIndex - } - return 0 -} - -func (m *TxRequestDetailsType) GetTxHash() []byte { - if m != nil { - return m.TxHash - } - return nil -} - -func (m *TxRequestDetailsType) GetExtraDataLen() uint32 { - if m != nil && m.ExtraDataLen != nil { - return *m.ExtraDataLen - } - return 0 -} - -func (m *TxRequestDetailsType) GetExtraDataOffset() uint32 { - if m != nil && m.ExtraDataOffset != nil { - return *m.ExtraDataOffset - } - return 0 -} - -// * -// Structure representing serialized data -// @used_in TxRequest -type TxRequestSerializedType struct { - SignatureIndex *uint32 `protobuf:"varint,1,opt,name=signature_index,json=signatureIndex" json:"signature_index,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - SerializedTx []byte `protobuf:"bytes,3,opt,name=serialized_tx,json=serializedTx" json:"serialized_tx,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *TxRequestSerializedType) Reset() { *m = TxRequestSerializedType{} } -func (m *TxRequestSerializedType) String() string { return proto.CompactTextString(m) } -func (*TxRequestSerializedType) ProtoMessage() {} -func (*TxRequestSerializedType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } - -func (m *TxRequestSerializedType) GetSignatureIndex() uint32 { - if m != nil && m.SignatureIndex != nil { - return *m.SignatureIndex - } - return 0 -} - -func (m *TxRequestSerializedType) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *TxRequestSerializedType) GetSerializedTx() []byte { - if m != nil { - return m.SerializedTx - } - return nil -} - -// * -// Structure representing identity data -// @used_in IdentityType -type IdentityType struct { - Proto *string `protobuf:"bytes,1,opt,name=proto" json:"proto,omitempty"` - User *string `protobuf:"bytes,2,opt,name=user" json:"user,omitempty"` - Host *string `protobuf:"bytes,3,opt,name=host" json:"host,omitempty"` - Port *string `protobuf:"bytes,4,opt,name=port" json:"port,omitempty"` - Path *string `protobuf:"bytes,5,opt,name=path" json:"path,omitempty"` - Index *uint32 `protobuf:"varint,6,opt,name=index,def=0" json:"index,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *IdentityType) Reset() { *m = IdentityType{} } -func (m *IdentityType) String() string { return proto.CompactTextString(m) } -func (*IdentityType) ProtoMessage() {} -func (*IdentityType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } - -const Default_IdentityType_Index uint32 = 0 - -func (m *IdentityType) GetProto() string { - if m != nil && m.Proto != nil { - return *m.Proto - } - return "" -} - -func (m *IdentityType) GetUser() string { - if m != nil && m.User != nil { - return *m.User - } - return "" -} - -func (m *IdentityType) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *IdentityType) GetPort() string { - if m != nil && m.Port != nil { - return *m.Port - } - return "" -} - -func (m *IdentityType) GetPath() string { - if m != nil && m.Path != nil { - return *m.Path - } - return "" -} - -func (m *IdentityType) GetIndex() uint32 { - if m != nil && m.Index != nil { - return *m.Index - } - return Default_IdentityType_Index -} - -var E_WireIn = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50002, - Name: "wire_in", - Tag: "varint,50002,opt,name=wire_in,json=wireIn", - Filename: "types.proto", -} - -var E_WireOut = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50003, - Name: "wire_out", - Tag: "varint,50003,opt,name=wire_out,json=wireOut", - Filename: "types.proto", -} - -var E_WireDebugIn = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50004, - Name: "wire_debug_in", - Tag: "varint,50004,opt,name=wire_debug_in,json=wireDebugIn", - Filename: "types.proto", -} - -var E_WireDebugOut = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50005, - Name: "wire_debug_out", - Tag: "varint,50005,opt,name=wire_debug_out,json=wireDebugOut", - Filename: "types.proto", -} - -var E_WireTiny = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50006, - Name: "wire_tiny", - Tag: "varint,50006,opt,name=wire_tiny,json=wireTiny", - Filename: "types.proto", -} - -var E_WireBootloader = &proto.ExtensionDesc{ - ExtendedType: (*google_protobuf.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50007, - Name: "wire_bootloader", - Tag: "varint,50007,opt,name=wire_bootloader,json=wireBootloader", - Filename: "types.proto", -} - -func init() { - proto.RegisterType((*HDNodeType)(nil), "HDNodeType") - proto.RegisterType((*HDNodePathType)(nil), "HDNodePathType") - proto.RegisterType((*CoinType)(nil), "CoinType") - proto.RegisterType((*MultisigRedeemScriptType)(nil), "MultisigRedeemScriptType") - proto.RegisterType((*TxInputType)(nil), "TxInputType") - proto.RegisterType((*TxOutputType)(nil), "TxOutputType") - proto.RegisterType((*TxOutputBinType)(nil), "TxOutputBinType") - proto.RegisterType((*TransactionType)(nil), "TransactionType") - proto.RegisterType((*TxRequestDetailsType)(nil), "TxRequestDetailsType") - proto.RegisterType((*TxRequestSerializedType)(nil), "TxRequestSerializedType") - proto.RegisterType((*IdentityType)(nil), "IdentityType") - proto.RegisterEnum("FailureType", FailureType_name, FailureType_value) - proto.RegisterEnum("OutputScriptType", OutputScriptType_name, OutputScriptType_value) - proto.RegisterEnum("InputScriptType", InputScriptType_name, InputScriptType_value) - proto.RegisterEnum("RequestType", RequestType_name, RequestType_value) - proto.RegisterEnum("ButtonRequestType", ButtonRequestType_name, ButtonRequestType_value) - proto.RegisterEnum("PinMatrixRequestType", PinMatrixRequestType_name, PinMatrixRequestType_value) - proto.RegisterEnum("RecoveryDeviceType", RecoveryDeviceType_name, RecoveryDeviceType_value) - proto.RegisterEnum("WordRequestType", WordRequestType_name, WordRequestType_value) - proto.RegisterExtension(E_WireIn) - proto.RegisterExtension(E_WireOut) - proto.RegisterExtension(E_WireDebugIn) - proto.RegisterExtension(E_WireDebugOut) - proto.RegisterExtension(E_WireTiny) - proto.RegisterExtension(E_WireBootloader) -} - -func init() { proto.RegisterFile("types.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 1899 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x72, 0x1a, 0xc9, - 0x19, 0xf6, 0x00, 0x92, 0xe0, 0x07, 0xc4, 0xa8, 0x7d, 0xd0, 0x78, 0x6d, 0xaf, 0x31, 0x76, 0x62, - 0x45, 0x55, 0x61, 0x77, 0xc9, 0x5a, 0x8e, 0x55, 0xa9, 0x24, 0x3a, 0xa0, 0x15, 0x65, 0x0b, 0x51, - 0xc3, 0x28, 0x56, 0x72, 0x33, 0x35, 0xcc, 0xb4, 0xa0, 0x4b, 0x43, 0x37, 0xe9, 0xe9, 0x91, 0xd1, - 0xde, 0xe4, 0x2a, 0xc9, 0x55, 0x5e, 0x23, 0x6f, 0x91, 0xaa, 0xbc, 0x41, 0xaa, 0x36, 0xa7, 0xcb, - 0xbc, 0x41, 0xae, 0xf2, 0x00, 0xa9, 0x3e, 0x0c, 0x02, 0xc9, 0xde, 0xd2, 0x1d, 0xfd, 0x7d, 0xff, - 0xf9, 0xd0, 0x3d, 0x40, 0x59, 0x5c, 0x4e, 0x70, 0xd2, 0x9c, 0x70, 0x26, 0xd8, 0x67, 0xf5, 0x21, - 0x63, 0xc3, 0x18, 0x7f, 0xa1, 0x4e, 0x83, 0xf4, 0xec, 0x8b, 0x08, 0x27, 0x21, 0x27, 0x13, 0xc1, - 0xb8, 0x96, 0x68, 0xfc, 0xd5, 0x02, 0x38, 0xdc, 0xef, 0xb2, 0x08, 0x7b, 0x97, 0x13, 0x8c, 0xee, - 0xc1, 0x52, 0x84, 0x27, 0x62, 0xe4, 0x58, 0xf5, 0xdc, 0x46, 0xd5, 0xd5, 0x07, 0x54, 0x87, 0xf2, - 0x19, 0xa1, 0x43, 0xcc, 0x27, 0x9c, 0x50, 0xe1, 0xe4, 0x14, 0x37, 0x0f, 0xa1, 0x47, 0x50, 0x0a, - 0x47, 0x24, 0x8e, 0x7c, 0x9a, 0x8e, 0x9d, 0xbc, 0xe2, 0x8b, 0x0a, 0xe8, 0xa6, 0x63, 0xf4, 0x04, - 0x20, 0x1c, 0x05, 0x84, 0xfa, 0x21, 0x8b, 0xb0, 0x53, 0xa8, 0xe7, 0x36, 0x2a, 0x6e, 0x49, 0x21, - 0x7b, 0x2c, 0xc2, 0xe8, 0x29, 0x94, 0x27, 0x9c, 0x5c, 0x04, 0x02, 0xfb, 0xe7, 0xf8, 0xd2, 0x59, - 0xaa, 0x5b, 0x1b, 0x15, 0x17, 0x0c, 0xf4, 0x16, 0x5f, 0x4a, 0xfd, 0x49, 0x3a, 0x88, 0x49, 0xa8, - 0xf8, 0x65, 0xc5, 0x97, 0x34, 0xf2, 0x16, 0x5f, 0x36, 0xba, 0xb0, 0xaa, 0x33, 0xe8, 0x05, 0x62, - 0xa4, 0xb2, 0x78, 0x0a, 0x05, 0x2a, 0x5d, 0xc9, 0x24, 0xca, 0xad, 0x72, 0xf3, 0x2a, 0x41, 0x57, - 0x11, 0x32, 0xdc, 0x20, 0x8a, 0x38, 0x4e, 0x12, 0x9f, 0x3a, 0xb9, 0x7a, 0x5e, 0x86, 0x6b, 0x80, - 0x6e, 0xe3, 0x7f, 0x39, 0x28, 0xee, 0x31, 0x42, 0x95, 0x29, 0x99, 0x18, 0x23, 0xd4, 0xa7, 0xc1, - 0x58, 0xda, 0xb3, 0x36, 0x4a, 0x6e, 0x51, 0x02, 0xdd, 0x60, 0x8c, 0xd1, 0x73, 0xa8, 0x2a, 0x32, - 0x19, 0x31, 0x2e, 0xc2, 0x54, 0x56, 0x46, 0x0a, 0x54, 0x24, 0xd8, 0x37, 0x18, 0x7a, 0x01, 0x95, - 0xcc, 0x97, 0x6c, 0x8d, 0x93, 0xaf, 0x5b, 0x1b, 0xd5, 0x6d, 0xeb, 0x4b, 0xb7, 0x6c, 0xe0, 0xcc, - 0xcf, 0x38, 0x98, 0x9e, 0x61, 0xec, 0x9f, 0x0f, 0x9c, 0x42, 0xdd, 0xda, 0x28, 0xb8, 0x45, 0x0d, - 0xbc, 0x1d, 0xa0, 0x1f, 0xc3, 0xda, 0xbc, 0x09, 0x7f, 0xd2, 0x4a, 0x46, 0xaa, 0x4e, 0xd5, 0x6d, - 0xeb, 0x95, 0x5b, 0x9b, 0xb3, 0xd3, 0x6b, 0x25, 0x23, 0xd4, 0x82, 0xfb, 0x09, 0x19, 0x52, 0x1c, - 0xf9, 0x63, 0x9c, 0x24, 0xc1, 0x10, 0xfb, 0x23, 0x1c, 0x44, 0x98, 0x3b, 0x45, 0x15, 0xde, 0x5d, - 0x4d, 0x1e, 0x69, 0xee, 0x50, 0x51, 0xe8, 0x25, 0xc0, 0x74, 0x92, 0x0e, 0xfc, 0x71, 0x30, 0x24, - 0xa1, 0x53, 0x52, 0xb6, 0x8b, 0xaf, 0xb7, 0xbe, 0xdc, 0x7a, 0xfd, 0x93, 0x57, 0x3f, 0x75, 0x4b, - 0x92, 0x3b, 0x92, 0x94, 0x16, 0xe4, 0x17, 0x46, 0x10, 0xae, 0x04, 0xb7, 0x5a, 0xaf, 0xb7, 0xa4, - 0x20, 0xbf, 0xd0, 0x82, 0x0f, 0x60, 0x39, 0xc1, 0xc3, 0x0f, 0x44, 0x38, 0xe5, 0xba, 0xb5, 0x51, - 0x74, 0xcd, 0x49, 0xe2, 0x67, 0x8c, 0x9f, 0x93, 0xc8, 0xa9, 0x48, 0x65, 0xd7, 0x9c, 0x1a, 0x09, - 0x38, 0x47, 0x69, 0x2c, 0x48, 0x42, 0x86, 0x2e, 0x8e, 0x30, 0x1e, 0xf7, 0xd5, 0xa4, 0xaa, 0xea, - 0xfc, 0x08, 0x56, 0x26, 0xe9, 0xe0, 0x1c, 0x5f, 0x26, 0x8e, 0x55, 0xcf, 0x6f, 0x94, 0x5b, 0xb5, - 0xe6, 0x62, 0xcb, 0xdd, 0x8c, 0x47, 0x9f, 0x03, 0xc8, 0xfc, 0x02, 0x91, 0x72, 0x9c, 0xa8, 0xde, - 0x56, 0xdc, 0x39, 0x04, 0x55, 0xc0, 0x1a, 0xeb, 0x1e, 0xb8, 0xd6, 0xb8, 0xf1, 0x97, 0x1c, 0x94, - 0xbd, 0x69, 0x87, 0x4e, 0x52, 0x91, 0xb5, 0xe1, 0x6a, 0x30, 0xac, 0xc5, 0xc1, 0x90, 0xe4, 0x84, - 0xe3, 0x0b, 0x7f, 0x14, 0x24, 0x23, 0xb5, 0x04, 0x15, 0xb7, 0x28, 0x81, 0xc3, 0x20, 0x19, 0xa9, - 0x21, 0x95, 0x24, 0xa1, 0x11, 0x9e, 0x9a, 0x15, 0x50, 0xe2, 0x1d, 0x09, 0x48, 0x5a, 0x6f, 0x9e, - 0x9f, 0x90, 0xa1, 0x6a, 0x70, 0xc5, 0x2d, 0x69, 0xa4, 0x4f, 0x86, 0xe8, 0x87, 0x50, 0x4c, 0xf0, - 0x6f, 0x53, 0x4c, 0x43, 0x6c, 0x1a, 0x0b, 0x5f, 0xb7, 0xde, 0x7c, 0xfd, 0x66, 0xeb, 0x75, 0xeb, - 0xcd, 0x2b, 0x77, 0xc6, 0xa1, 0x5f, 0x40, 0xd9, 0x98, 0x51, 0xb3, 0x24, 0x77, 0x61, 0xb5, 0x65, - 0x37, 0x55, 0x02, 0x57, 0xf5, 0xda, 0xae, 0xf4, 0x7b, 0xed, 0xee, 0xfe, 0xce, 0xfe, 0xbe, 0xdb, - 0xee, 0xf7, 0x5d, 0xe3, 0x59, 0x25, 0xf8, 0x0a, 0x8a, 0x63, 0x53, 0x65, 0x67, 0xa5, 0x6e, 0x6d, - 0x94, 0x5b, 0x0f, 0x9b, 0x9f, 0x2a, 0xbb, 0x3b, 0x13, 0x95, 0x4d, 0x0b, 0xc6, 0x2c, 0xa5, 0x42, - 0xcd, 0x50, 0xc1, 0x35, 0xa7, 0xc6, 0x7f, 0x2d, 0xa8, 0x78, 0xd3, 0xe3, 0x54, 0x64, 0x05, 0x74, - 0x60, 0xc5, 0xd4, 0xcb, 0x6c, 0x4b, 0x76, 0xfc, 0xde, 0x9d, 0x9b, 0xb3, 0x2f, 0x2b, 0x37, 0xb3, - 0x8f, 0x5a, 0x8b, 0xf9, 0xca, 0xbb, 0x63, 0xb5, 0xb5, 0xd6, 0xd4, 0x0e, 0xe7, 0x22, 0xfd, 0x54, - 0x8a, 0x4b, 0xb7, 0x4f, 0xf1, 0x05, 0xac, 0xb2, 0x89, 0xcf, 0xb1, 0x48, 0x39, 0xf5, 0xa3, 0x40, - 0x04, 0xe6, 0xa6, 0xa9, 0xb0, 0x89, 0xab, 0xc0, 0xfd, 0x40, 0x04, 0x8d, 0x2e, 0xd4, 0xb2, 0x7c, - 0x77, 0xcd, 0x15, 0x71, 0x15, 0xbb, 0xb5, 0x10, 0xfb, 0x73, 0xa8, 0x9a, 0xd8, 0xf5, 0x6c, 0x9a, - 0x91, 0xa9, 0x68, 0xb0, 0xa7, 0xb0, 0xc6, 0xdf, 0x72, 0x50, 0xf3, 0x78, 0x40, 0x93, 0x20, 0x14, - 0x84, 0xd1, 0xac, 0x86, 0x17, 0x98, 0x27, 0x84, 0x51, 0x55, 0xc3, 0xaa, 0x9b, 0x1d, 0xd1, 0x0b, - 0x58, 0x26, 0xb2, 0xd5, 0x7a, 0xb0, 0xcb, 0xad, 0x4a, 0x73, 0x6e, 0x78, 0x5d, 0xc3, 0xa1, 0xaf, - 0xa0, 0x3c, 0x20, 0xd4, 0x67, 0x2a, 0xca, 0xc4, 0xc9, 0x2b, 0x51, 0xbb, 0x79, 0x2d, 0x6e, 0x17, - 0x06, 0x84, 0x6a, 0x24, 0x41, 0x2f, 0x61, 0x25, 0x13, 0x5f, 0x52, 0xe2, 0xd5, 0xe6, 0x7c, 0x5b, - 0xdd, 0x8c, 0x95, 0x5d, 0x8c, 0x59, 0x78, 0xee, 0x0b, 0x32, 0xc6, 0x6a, 0x8c, 0xab, 0x6e, 0x51, - 0x02, 0x1e, 0x19, 0x63, 0x39, 0xe4, 0x3a, 0x04, 0x3f, 0xa4, 0x42, 0x95, 0xaf, 0xea, 0x96, 0x34, - 0xb2, 0x47, 0x85, 0xbc, 0xe8, 0x8d, 0x19, 0xc5, 0xaf, 0x28, 0x1e, 0x0c, 0x24, 0x05, 0x9e, 0x00, - 0xe0, 0xa9, 0xe0, 0x81, 0x2e, 0x7f, 0x51, 0x2f, 0x89, 0x42, 0x64, 0xed, 0x65, 0x87, 0xae, 0x68, - 0x3f, 0xc6, 0x54, 0xdf, 0x53, 0x6e, 0x65, 0x26, 0xf2, 0x0e, 0xd3, 0xc6, 0x9f, 0x2d, 0xb8, 0xe7, - 0x4d, 0x5d, 0xb9, 0x31, 0x89, 0xd8, 0xc7, 0x22, 0x20, 0xb1, 0xbe, 0x62, 0x9f, 0x43, 0x95, 0x6b, - 0xd4, 0x2c, 0xa9, 0x2e, 0x6e, 0xc5, 0x80, 0x7a, 0x4f, 0xd7, 0x61, 0x45, 0x4c, 0xb3, 0x0d, 0x97, - 0xfe, 0x97, 0xc5, 0x54, 0xed, 0xf7, 0x4d, 0xe7, 0xf9, 0x9b, 0xce, 0xd1, 0x26, 0xac, 0xcd, 0x49, - 0xb1, 0xb3, 0xb3, 0x04, 0x0b, 0x53, 0xa6, 0xda, 0x4c, 0xf0, 0x58, 0xc1, 0x8d, 0xdf, 0x5b, 0xb0, - 0x3e, 0x0b, 0xb4, 0x8f, 0x39, 0x09, 0x62, 0xf2, 0x2d, 0x8e, 0x54, 0xac, 0x2f, 0xa1, 0x36, 0xbb, - 0xb3, 0x16, 0xa2, 0x5d, 0x9d, 0xc1, 0x3a, 0xde, 0xc7, 0x50, 0x9a, 0x21, 0x26, 0xe2, 0x2b, 0x40, - 0x8d, 0xe0, 0xcc, 0xb0, 0x2f, 0xa6, 0x2a, 0x66, 0x39, 0x82, 0x57, 0xde, 0xa6, 0x8d, 0x3f, 0x59, - 0x50, 0xe9, 0x44, 0x98, 0x0a, 0x22, 0x2e, 0xb3, 0x8f, 0x00, 0xf5, 0x71, 0x60, 0x36, 0x58, 0x1f, - 0x10, 0x82, 0x42, 0x9a, 0x60, 0x6e, 0xde, 0x38, 0xf5, 0x5b, 0x62, 0x23, 0x96, 0x08, 0x65, 0xb6, - 0xe4, 0xaa, 0xdf, 0x12, 0x9b, 0x30, 0xae, 0xb3, 0x2e, 0xb9, 0xea, 0xb7, 0xc2, 0x02, 0xa1, 0xdf, - 0x2c, 0x89, 0x05, 0x62, 0x84, 0xd6, 0x61, 0x49, 0x27, 0xb6, 0x9c, 0x3d, 0x88, 0xfa, 0xbc, 0xf9, - 0x5d, 0x0e, 0xca, 0x07, 0x01, 0x89, 0x53, 0xae, 0xbf, 0x49, 0x9e, 0xc0, 0x43, 0x73, 0xf4, 0x4f, - 0x28, 0x9e, 0x4e, 0x70, 0x28, 0x66, 0xaf, 0x97, 0x6d, 0xa1, 0xcf, 0xe0, 0x41, 0x46, 0xef, 0xa6, - 0x42, 0x30, 0xda, 0x36, 0x22, 0x76, 0x0e, 0xdd, 0x87, 0xb5, 0x8c, 0x93, 0x85, 0x6f, 0x73, 0xce, - 0xb8, 0x9d, 0x47, 0x8f, 0x60, 0x3d, 0x83, 0x77, 0xd4, 0xda, 0xed, 0x05, 0x34, 0xc4, 0x71, 0x8c, - 0x23, 0xbb, 0x80, 0xd6, 0xe1, 0x6e, 0x46, 0xf6, 0xc8, 0x95, 0xb1, 0x25, 0xe4, 0xc0, 0xbd, 0x39, - 0xe2, 0x4a, 0x65, 0x19, 0x3d, 0x00, 0x34, 0xc7, 0x74, 0xe8, 0x45, 0x10, 0x93, 0xc8, 0x5e, 0x41, - 0x8f, 0xc1, 0xc9, 0x70, 0x03, 0xf6, 0xb3, 0xd6, 0xd8, 0xc5, 0x05, 0x7b, 0x9c, 0x85, 0x38, 0x49, - 0x74, 0x7c, 0xa5, 0xf9, 0x94, 0xba, 0x4c, 0xb4, 0x29, 0x4b, 0x87, 0xa3, 0x83, 0x94, 0x46, 0x89, - 0x0d, 0xd7, 0xb8, 0x0e, 0x25, 0xc2, 0x74, 0xd2, 0x2e, 0xa3, 0x87, 0x70, 0x3f, 0xe3, 0x0e, 0x08, - 0x1f, 0x7f, 0x08, 0x38, 0xd6, 0x26, 0xc3, 0xcd, 0x3f, 0x5a, 0x60, 0x5f, 0xbf, 0x35, 0x91, 0x0d, - 0x95, 0xde, 0xce, 0xaf, 0xbd, 0x63, 0xf3, 0x50, 0xd8, 0x77, 0xd0, 0x5d, 0xa8, 0x29, 0xa4, 0xbf, - 0xe7, 0x76, 0x7a, 0xde, 0xe1, 0x4e, 0xff, 0xd0, 0xb6, 0xd0, 0x1a, 0x54, 0x15, 0x78, 0x74, 0xf2, - 0xce, 0xeb, 0xf4, 0x3b, 0xdf, 0xd8, 0xb9, 0x19, 0x74, 0xdc, 0x73, 0xdb, 0xde, 0x89, 0xdb, 0xb5, - 0xf3, 0x33, 0x63, 0xef, 0x3b, 0x5e, 0x57, 0x1a, 0x2b, 0xa0, 0x7b, 0x60, 0x2b, 0xa4, 0xd7, 0xea, - 0x1f, 0x66, 0xe8, 0xd2, 0x66, 0x0c, 0xb5, 0x6b, 0xcf, 0x95, 0x54, 0x9d, 0x7f, 0xb0, 0xec, 0x3b, - 0xd2, 0xbe, 0x42, 0x66, 0x2e, 0x2d, 0x54, 0x81, 0x62, 0xfb, 0xd4, 0x6b, 0xbb, 0xdd, 0x9d, 0x77, - 0x76, 0x6e, 0xa6, 0x92, 0xd9, 0xcd, 0x4b, 0x6f, 0x0a, 0x99, 0xf7, 0x56, 0xd8, 0x3c, 0x81, 0xb2, - 0xd9, 0x30, 0xe5, 0xa9, 0x0c, 0x2b, 0xde, 0x69, 0xa7, 0xdb, 0x3b, 0xf1, 0xec, 0x3b, 0xd2, 0xa2, - 0x77, 0x7a, 0x7c, 0xe2, 0xc9, 0x93, 0x85, 0x00, 0x96, 0xbd, 0xd3, 0xa3, 0xb6, 0xb7, 0x63, 0xe7, - 0xd0, 0x2a, 0x80, 0x77, 0x7a, 0xd0, 0xe9, 0x76, 0xfa, 0x87, 0xed, 0x7d, 0x3b, 0x8f, 0x6a, 0x50, - 0xf6, 0x4e, 0xdb, 0xa7, 0x9e, 0xbb, 0xb3, 0xbf, 0xe3, 0xed, 0xd8, 0x85, 0xcd, 0xff, 0xe4, 0x60, - 0x4d, 0x4f, 0xdb, 0xbc, 0xf5, 0x75, 0xb8, 0xbb, 0x00, 0xfa, 0xc7, 0x62, 0x84, 0xb9, 0x6d, 0xa1, - 0x06, 0x7c, 0xbe, 0x48, 0x1c, 0x60, 0x7c, 0x7c, 0x81, 0xb9, 0x37, 0xe2, 0x38, 0x19, 0xb1, 0x58, - 0xce, 0xea, 0x53, 0x78, 0xb4, 0x28, 0xb3, 0xc7, 0xe8, 0x19, 0xe1, 0x63, 0xdd, 0x35, 0x3b, 0x2f, - 0xf7, 0x60, 0x51, 0xc0, 0xc5, 0x09, 0x16, 0xfb, 0xf8, 0x82, 0x84, 0xd8, 0x2e, 0xdc, 0xa4, 0x8d, - 0xfe, 0x7b, 0xc6, 0xe5, 0xf4, 0x3e, 0x06, 0x67, 0x91, 0x7e, 0x4f, 0x26, 0xd8, 0x28, 0x2f, 0xdf, - 0x54, 0xee, 0x71, 0x26, 0x70, 0x28, 0xf6, 0x82, 0x38, 0xb6, 0x57, 0xe4, 0xa8, 0x2e, 0xd2, 0x72, - 0x8e, 0xbd, 0xa9, 0x5d, 0xbc, 0x19, 0x75, 0x36, 0x78, 0x7b, 0x23, 0x1c, 0x9e, 0xdb, 0x25, 0x39, - 0x93, 0x8b, 0x02, 0x3b, 0xfa, 0xcd, 0xb7, 0x41, 0xae, 0xe1, 0x35, 0xa7, 0xd9, 0x37, 0xbd, 0x5d, - 0xde, 0xfc, 0x1d, 0xdc, 0xeb, 0x11, 0x7a, 0x14, 0x08, 0x4e, 0xa6, 0xf3, 0x35, 0xae, 0xc3, 0xe3, - 0x8f, 0xe1, 0xfe, 0x5e, 0xca, 0x39, 0xa6, 0xc2, 0xb6, 0xd0, 0x33, 0x78, 0xf2, 0x51, 0x89, 0x2e, - 0xfe, 0x70, 0x40, 0x78, 0x22, 0xec, 0x9c, 0xec, 0xc7, 0xa7, 0x44, 0xfa, 0x38, 0x64, 0x34, 0xb2, - 0xf3, 0x9b, 0xbf, 0x01, 0xe4, 0xe2, 0x90, 0x5d, 0x60, 0x7e, 0xa9, 0xcb, 0xa4, 0xdc, 0xff, 0x00, - 0x9e, 0xdd, 0x44, 0xfd, 0x7e, 0xc8, 0x83, 0xf1, 0x20, 0xc6, 0x91, 0x2c, 0x76, 0x62, 0xdf, 0x91, - 0xf5, 0xfc, 0x88, 0x98, 0x76, 0x68, 0x5b, 0x9b, 0x67, 0x50, 0x93, 0x92, 0xf3, 0x79, 0x3d, 0x84, - 0xfb, 0xd7, 0x20, 0xbf, 0x17, 0x07, 0x84, 0xda, 0x77, 0x64, 0x9d, 0xae, 0x53, 0xda, 0xd2, 0x1b, - 0xdb, 0xfa, 0x34, 0xb9, 0x65, 0xe7, 0xb6, 0x7f, 0x06, 0x2b, 0x1f, 0x88, 0x7a, 0x41, 0xd0, 0xb3, - 0xa6, 0xfe, 0x2f, 0xd8, 0xcc, 0xfe, 0x0b, 0x36, 0xdb, 0x34, 0x1d, 0xff, 0x2a, 0x88, 0x53, 0x7c, - 0x3c, 0x91, 0x77, 0x60, 0xe2, 0x7c, 0xf7, 0x87, 0xbc, 0xfe, 0x52, 0x97, 0x3a, 0x1d, 0xba, 0xfd, - 0x73, 0x28, 0x2a, 0x6d, 0x96, 0x8a, 0xdb, 0xa8, 0xff, 0xdd, 0xa8, 0x2b, 0x97, 0xc7, 0xa9, 0xd8, - 0xfe, 0x06, 0xaa, 0x4a, 0x3f, 0xc2, 0x83, 0x74, 0x78, 0xcb, 0x18, 0xfe, 0x61, 0x8c, 0x94, 0xa5, - 0xe6, 0xbe, 0x54, 0xec, 0xd0, 0xed, 0x0e, 0xac, 0xce, 0x19, 0xba, 0x65, 0x38, 0xff, 0x34, 0x96, - 0x2a, 0x33, 0x4b, 0x32, 0xa6, 0x5f, 0x42, 0x49, 0x99, 0x12, 0x84, 0x5e, 0xde, 0xc6, 0xca, 0xbf, - 0x8c, 0x15, 0x55, 0x09, 0x8f, 0xd0, 0xcb, 0xed, 0x77, 0x50, 0x53, 0x16, 0x06, 0x8c, 0x89, 0x98, - 0xa9, 0x3f, 0x4f, 0xb7, 0xb0, 0xf3, 0x6f, 0x63, 0x47, 0x25, 0xb2, 0x3b, 0x53, 0xdd, 0xfd, 0x0a, - 0x9e, 0x87, 0x6c, 0xdc, 0x4c, 0x02, 0xc1, 0x92, 0x11, 0x89, 0x83, 0x41, 0xd2, 0x14, 0x1c, 0x7f, - 0xcb, 0x78, 0x33, 0x26, 0x83, 0x99, 0xbd, 0x5d, 0xf0, 0x14, 0x28, 0xdb, 0xfb, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x70, 0x88, 0xcd, 0x71, 0xe2, 0x0f, 0x00, 0x00, -} 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 deleted file mode 100644 index acbe79e3f..000000000 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.proto +++ /dev/null @@ -1,278 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/types.proto -// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b. - -syntax = "proto2"; - -/** - * Types for TREZOR communication - * - * @author Marek Palatinus - * @version 1.2 - */ - -// Sugar for easier handling in Java -option java_package = "com.satoshilabs.trezor.lib.protobuf"; -option java_outer_classname = "TrezorType"; - -import "google/protobuf/descriptor.proto"; - -/** - * Options for specifying message direction and type of wire (normal/debug) - */ -extend google.protobuf.EnumValueOptions { - optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR - optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC - optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR - optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC - optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode - optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader -} - -/** - * Type of failures returned by Failure message - * @used_in Failure - */ -enum FailureType { - Failure_UnexpectedMessage = 1; - Failure_ButtonExpected = 2; - Failure_DataError = 3; - Failure_ActionCancelled = 4; - Failure_PinExpected = 5; - Failure_PinCancelled = 6; - Failure_PinInvalid = 7; - Failure_InvalidSignature = 8; - Failure_ProcessError = 9; - Failure_NotEnoughFunds = 10; - Failure_NotInitialized = 11; - Failure_FirmwareError = 99; -} - -/** - * Type of script which will be used for transaction output - * @used_in TxOutputType - */ -enum OutputScriptType { - PAYTOADDRESS = 0; // used for all addresses (bitcoin, p2sh, witness) - PAYTOSCRIPTHASH = 1; // p2sh address (deprecated; use PAYTOADDRESS) - PAYTOMULTISIG = 2; // only for change output - PAYTOOPRETURN = 3; // op_return - PAYTOWITNESS = 4; // only for change output - PAYTOP2SHWITNESS = 5; // only for change output -} - -/** - * Type of script which will be used for transaction output - * @used_in TxInputType - */ -enum InputScriptType { - SPENDADDRESS = 0; // standard p2pkh address - SPENDMULTISIG = 1; // p2sh multisig address - EXTERNAL = 2; // reserved for external inputs (coinjoin) - SPENDWITNESS = 3; // native segwit - SPENDP2SHWITNESS = 4; // segwit over p2sh (backward compatible) -} - -/** - * Type of information required by transaction signing process - * @used_in TxRequest - */ -enum RequestType { - TXINPUT = 0; - TXOUTPUT = 1; - TXMETA = 2; - TXFINISHED = 3; - TXEXTRADATA = 4; -} - -/** - * Type of button request - * @used_in ButtonRequest - */ -enum ButtonRequestType { - ButtonRequest_Other = 1; - ButtonRequest_FeeOverThreshold = 2; - ButtonRequest_ConfirmOutput = 3; - ButtonRequest_ResetDevice = 4; - ButtonRequest_ConfirmWord = 5; - ButtonRequest_WipeDevice = 6; - ButtonRequest_ProtectCall = 7; - ButtonRequest_SignTx = 8; - ButtonRequest_FirmwareCheck = 9; - ButtonRequest_Address = 10; - ButtonRequest_PublicKey = 11; -} - -/** - * Type of PIN request - * @used_in PinMatrixRequest - */ -enum PinMatrixRequestType { - PinMatrixRequestType_Current = 1; - PinMatrixRequestType_NewFirst = 2; - PinMatrixRequestType_NewSecond = 3; -} - -/** - * Type of recovery procedure. These should be used as bitmask, e.g., - * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` - * listing every method supported by the host computer. - * - * Note that ScrambledWords must be supported by every implementation - * for backward compatibility; there is no way to not support it. - * - * @used_in RecoveryDevice - */ -enum RecoveryDeviceType { - // use powers of two when extending this field - RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order - RecoveryDeviceType_Matrix = 1; // matrix recovery type -} - -/** - * Type of Recovery Word request - * @used_in WordRequest - */ -enum WordRequestType { - WordRequestType_Plain = 0; - WordRequestType_Matrix9 = 1; - WordRequestType_Matrix6 = 2; -} - -/** - * Structure representing BIP32 (hierarchical deterministic) node - * Used for imports of private key into the device and exporting public key out of device - * @used_in PublicKey - * @used_in LoadDevice - * @used_in DebugLinkState - * @used_in Storage - */ -message HDNodeType { - required uint32 depth = 1; - required uint32 fingerprint = 2; - required uint32 child_num = 3; - required bytes chain_code = 4; - optional bytes private_key = 5; - optional bytes public_key = 6; -} - -message HDNodePathType { - required HDNodeType node = 1; // BIP-32 node in deserialized form - repeated uint32 address_n = 2; // BIP-32 path to derive the key from node -} - -/** - * Structure representing Coin - * @used_in Features - */ -message CoinType { - optional string coin_name = 1; - optional string coin_shortcut = 2; - optional uint32 address_type = 3 [default=0]; - optional uint64 maxfee_kb = 4; - optional uint32 address_type_p2sh = 5 [default=5]; - optional string signed_message_header = 8; - optional uint32 xpub_magic = 9 [default=76067358]; // default=0x0488b21e - optional uint32 xprv_magic = 10 [default=76066276]; // default=0x0488ade4 - optional bool segwit = 11; - optional uint32 forkid = 12; -} - -/** - * Type of redeem script used in input - * @used_in TxInputType - */ -message MultisigRedeemScriptType { - repeated HDNodePathType pubkeys = 1; // pubkeys from multisig address (sorted lexicographically) - repeated bytes signatures = 2; // existing signatures for partially signed input - optional uint32 m = 3; // "m" from n, how many valid signatures is necessary for spending -} - -/** - * Structure representing transaction input - * @used_in SimpleSignTx - * @used_in TransactionType - */ -message TxInputType { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - required bytes prev_hash = 2; // hash of previous transaction output to spend by this input - required uint32 prev_index = 3; // index of previous output to spend - optional bytes script_sig = 4; // script signature, unset for tx to sign - optional uint32 sequence = 5 [default=4294967295]; // sequence (default=0xffffffff) - optional InputScriptType script_type = 6 [default=SPENDADDRESS]; // defines template of input script - optional MultisigRedeemScriptType multisig = 7; // Filled if input is going to spend multisig tx - optional uint64 amount = 8; // amount of previous transaction output (for segwit only) -} - -/** - * Structure representing transaction output - * @used_in SimpleSignTx - * @used_in TransactionType - */ -message TxOutputType { - optional string address = 1; // target coin address in Base58 encoding - repeated uint32 address_n = 2; // BIP-32 path to derive the key from master node; has higher priority than "address" - required uint64 amount = 3; // amount to spend in satoshis - required OutputScriptType script_type = 4; // output script type - optional MultisigRedeemScriptType multisig = 5; // defines multisig address; script_type must be PAYTOMULTISIG - optional bytes op_return_data = 6; // defines op_return data; script_type must be PAYTOOPRETURN, amount must be 0 -} - -/** - * Structure representing compiled transaction output - * @used_in TransactionType - */ -message TxOutputBinType { - required uint64 amount = 1; - required bytes script_pubkey = 2; -} - -/** - * Structure representing transaction - * @used_in SimpleSignTx - */ -message TransactionType { - optional uint32 version = 1; - repeated TxInputType inputs = 2; - repeated TxOutputBinType bin_outputs = 3; - repeated TxOutputType outputs = 5; - optional uint32 lock_time = 4; - optional uint32 inputs_cnt = 6; - optional uint32 outputs_cnt = 7; - optional bytes extra_data = 8; - optional uint32 extra_data_len = 9; -} - -/** - * Structure representing request details - * @used_in TxRequest - */ -message TxRequestDetailsType { - optional uint32 request_index = 1; // device expects TxAck message from the computer - optional bytes tx_hash = 2; // tx_hash of requested transaction - optional uint32 extra_data_len = 3; // length of requested extra data - optional uint32 extra_data_offset = 4; // offset of requested extra data -} - -/** - * Structure representing serialized data - * @used_in TxRequest - */ -message TxRequestSerializedType { - optional uint32 signature_index = 1; // 'signature' field contains signed input of this index - optional bytes signature = 2; // signature of the signature_index input - optional bytes serialized_tx = 3; // part of serialized and signed transaction -} - -/** - * Structure representing identity data - * @used_in IdentityType - */ -message IdentityType { - optional string proto = 1; // proto part of URI - optional string user = 2; // user part of URI - optional string host = 3; // host part of URI - optional string port = 4; // port part of URI - optional string path = 5; // path part of URI - optional uint32 index = 6 [default=0]; // identity index -} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go index c30903b5b..17ca9223f 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/ledger.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction op = ledgerP1ContTransactionData } // Extract the Ethereum signature and do a sanity validation - if len(reply) != 65 { + if len(reply) != crypto.SignatureLength { return common.Address{}, nil, errors.New("reply lacks signature") } signature := append(reply[1:], reply[0]) 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 a9d2e9959..1892097ba 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go @@ -28,7 +28,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor" + "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -41,6 +41,9 @@ import ( // encoded passphrase. var ErrTrezorPINNeeded = errors.New("trezor: pin needed") +// ErrTrezorPassphraseNeeded is returned if opening the trezor requires a passphrase +var ErrTrezorPassphraseNeeded = errors.New("trezor: passphrase needed") + // errTrezorReplyInvalidHeader is the error message returned by a Trezor data exchange // if the device replies with a mismatching header. This usually means the device // is in browser mode. @@ -48,12 +51,13 @@ var errTrezorReplyInvalidHeader = errors.New("trezor: invalid reply header") // trezorDriver implements the communication with a Trezor hardware wallet. type trezorDriver struct { - device io.ReadWriter // USB device connection to communicate through - version [3]uint32 // Current version of the Trezor firmware - label string // Current textual label of the Trezor device - pinwait bool // Flags whether the device is waiting for PIN entry - failure error // Any failure that would make the device unusable - log log.Logger // Contextual logger to tag the trezor with its id + device io.ReadWriter // USB device connection to communicate through + version [3]uint32 // Current version of the Trezor firmware + label string // Current textual label of the Trezor device + pinwait bool // Flags whether the device is waiting for PIN entry + passphrasewait bool // Flags whether the device is waiting for passphrase entry + failure error // Any failure that would make the device unusable + log log.Logger // Contextual logger to tag the trezor with its id } // newTrezorDriver creates a new instance of a Trezor USB protocol driver. @@ -79,19 +83,21 @@ func (w *trezorDriver) Status() (string, error) { } // Open implements usbwallet.driver, attempting to initialize the connection to -// the Trezor hardware wallet. Initializing the Trezor is a two phase operation: +// the Trezor hardware wallet. Initializing the Trezor is a two or three phase operation: // * The first phase is to initialize the connection and read the wallet's -// features. This phase is invoked is the provided passphrase is empty. The +// features. This phase is invoked if the provided passphrase is empty. The // device will display the pinpad as a result and will return an appropriate // error to notify the user that a second open phase is needed. // * The second phase is to unlock access to the Trezor, which is done by the // user actually providing a passphrase mapping a keyboard keypad to the pin // number of the user (shuffled according to the pinpad displayed). +// * If needed the device will ask for passphrase which will require calling +// open again with the actual passphrase (3rd phase) func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error { w.device, w.failure = device, nil // If phase 1 is requested, init the connection and wait for user callback - if passphrase == "" { + if passphrase == "" && !w.passphrasewait { // If we're already waiting for a PIN entry, insta-return if w.pinwait { return ErrTrezorPINNeeded @@ -104,26 +110,46 @@ func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error { w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()} w.label = features.GetLabel() - // Do a manual ping, forcing the device to ask for its PIN + // Do a manual ping, forcing the device to ask for its PIN and Passphrase askPin := true - res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin}, new(trezor.PinMatrixRequest), new(trezor.Success)) + askPassphrase := true + res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin, PassphraseProtection: &askPassphrase}, new(trezor.PinMatrixRequest), new(trezor.PassphraseRequest), new(trezor.Success)) if err != nil { return err } // Only return the PIN request if the device wasn't unlocked until now - if res == 1 { - return nil // Device responded with trezor.Success + switch res { + case 0: + w.pinwait = true + return ErrTrezorPINNeeded + case 1: + w.pinwait = false + w.passphrasewait = true + return ErrTrezorPassphraseNeeded + case 2: + return nil // responded with trezor.Success } - w.pinwait = true - return ErrTrezorPINNeeded } // Phase 2 requested with actual PIN entry - w.pinwait = false - - if _, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success)); err != nil { - w.failure = err - return err + if w.pinwait { + w.pinwait = false + res, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success), new(trezor.PassphraseRequest)) + if err != nil { + w.failure = err + return err + } + if res == 1 { + w.passphrasewait = true + return ErrTrezorPassphraseNeeded + } + } else if w.passphrasewait { + w.passphrasewait = false + if _, err := w.trezorExchange(&trezor.PassphraseAck{Passphrase: &passphrase}, new(trezor.Success)); err != nil { + w.failure = err + return err + } } + return nil } @@ -166,7 +192,13 @@ func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, er if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil { return common.Address{}, err } - return common.BytesToAddress(address.GetAddress()), nil + if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary fomats + return common.BytesToAddress(addr), nil + } + if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal fomats + return common.HexToAddress(addr), nil + } + return common.Address{}, errors.New("missing derived address") } // trezorSign sends the transaction to the Trezor wallet, and waits for the user @@ -185,7 +217,10 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction DataLength: &length, } if to := tx.To(); to != nil { - request.To = (*to)[:] // Non contract deploy, set recipient explicitly + // Non contract deploy, set recipient explicitly + hex := to.Hex() + request.ToHex = &hex // Newer firmwares (old will ignore) + request.ToBin = (*to)[:] // Older firmwares (new will ignore) } if length > 1024 { // Send the data chunked if that was requested request.DataInitialChunk, data = data[:1024], data[1024:] diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.pb.go new file mode 100644 index 000000000..304bec0e3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.pb.go @@ -0,0 +1,811 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages-common.proto + +package trezor + +import ( + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type Failure_FailureType int32 + +const ( + Failure_Failure_UnexpectedMessage Failure_FailureType = 1 + Failure_Failure_ButtonExpected Failure_FailureType = 2 + Failure_Failure_DataError Failure_FailureType = 3 + Failure_Failure_ActionCancelled Failure_FailureType = 4 + Failure_Failure_PinExpected Failure_FailureType = 5 + Failure_Failure_PinCancelled Failure_FailureType = 6 + Failure_Failure_PinInvalid Failure_FailureType = 7 + Failure_Failure_InvalidSignature Failure_FailureType = 8 + Failure_Failure_ProcessError Failure_FailureType = 9 + Failure_Failure_NotEnoughFunds Failure_FailureType = 10 + Failure_Failure_NotInitialized Failure_FailureType = 11 + Failure_Failure_PinMismatch Failure_FailureType = 12 + Failure_Failure_FirmwareError Failure_FailureType = 99 +) + +var Failure_FailureType_name = map[int32]string{ + 1: "Failure_UnexpectedMessage", + 2: "Failure_ButtonExpected", + 3: "Failure_DataError", + 4: "Failure_ActionCancelled", + 5: "Failure_PinExpected", + 6: "Failure_PinCancelled", + 7: "Failure_PinInvalid", + 8: "Failure_InvalidSignature", + 9: "Failure_ProcessError", + 10: "Failure_NotEnoughFunds", + 11: "Failure_NotInitialized", + 12: "Failure_PinMismatch", + 99: "Failure_FirmwareError", +} + +var Failure_FailureType_value = map[string]int32{ + "Failure_UnexpectedMessage": 1, + "Failure_ButtonExpected": 2, + "Failure_DataError": 3, + "Failure_ActionCancelled": 4, + "Failure_PinExpected": 5, + "Failure_PinCancelled": 6, + "Failure_PinInvalid": 7, + "Failure_InvalidSignature": 8, + "Failure_ProcessError": 9, + "Failure_NotEnoughFunds": 10, + "Failure_NotInitialized": 11, + "Failure_PinMismatch": 12, + "Failure_FirmwareError": 99, +} + +func (x Failure_FailureType) Enum() *Failure_FailureType { + p := new(Failure_FailureType) + *p = x + return p +} + +func (x Failure_FailureType) String() string { + return proto.EnumName(Failure_FailureType_name, int32(x)) +} + +func (x *Failure_FailureType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Failure_FailureType_value, data, "Failure_FailureType") + if err != nil { + return err + } + *x = Failure_FailureType(value) + return nil +} + +func (Failure_FailureType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{1, 0} +} + +//* +// Type of button request +type ButtonRequest_ButtonRequestType int32 + +const ( + ButtonRequest_ButtonRequest_Other ButtonRequest_ButtonRequestType = 1 + ButtonRequest_ButtonRequest_FeeOverThreshold ButtonRequest_ButtonRequestType = 2 + ButtonRequest_ButtonRequest_ConfirmOutput ButtonRequest_ButtonRequestType = 3 + ButtonRequest_ButtonRequest_ResetDevice ButtonRequest_ButtonRequestType = 4 + ButtonRequest_ButtonRequest_ConfirmWord ButtonRequest_ButtonRequestType = 5 + ButtonRequest_ButtonRequest_WipeDevice ButtonRequest_ButtonRequestType = 6 + ButtonRequest_ButtonRequest_ProtectCall ButtonRequest_ButtonRequestType = 7 + ButtonRequest_ButtonRequest_SignTx ButtonRequest_ButtonRequestType = 8 + ButtonRequest_ButtonRequest_FirmwareCheck ButtonRequest_ButtonRequestType = 9 + ButtonRequest_ButtonRequest_Address ButtonRequest_ButtonRequestType = 10 + ButtonRequest_ButtonRequest_PublicKey ButtonRequest_ButtonRequestType = 11 + ButtonRequest_ButtonRequest_MnemonicWordCount ButtonRequest_ButtonRequestType = 12 + ButtonRequest_ButtonRequest_MnemonicInput ButtonRequest_ButtonRequestType = 13 + ButtonRequest_ButtonRequest_PassphraseType ButtonRequest_ButtonRequestType = 14 + ButtonRequest_ButtonRequest_UnknownDerivationPath ButtonRequest_ButtonRequestType = 15 +) + +var ButtonRequest_ButtonRequestType_name = map[int32]string{ + 1: "ButtonRequest_Other", + 2: "ButtonRequest_FeeOverThreshold", + 3: "ButtonRequest_ConfirmOutput", + 4: "ButtonRequest_ResetDevice", + 5: "ButtonRequest_ConfirmWord", + 6: "ButtonRequest_WipeDevice", + 7: "ButtonRequest_ProtectCall", + 8: "ButtonRequest_SignTx", + 9: "ButtonRequest_FirmwareCheck", + 10: "ButtonRequest_Address", + 11: "ButtonRequest_PublicKey", + 12: "ButtonRequest_MnemonicWordCount", + 13: "ButtonRequest_MnemonicInput", + 14: "ButtonRequest_PassphraseType", + 15: "ButtonRequest_UnknownDerivationPath", +} + +var ButtonRequest_ButtonRequestType_value = map[string]int32{ + "ButtonRequest_Other": 1, + "ButtonRequest_FeeOverThreshold": 2, + "ButtonRequest_ConfirmOutput": 3, + "ButtonRequest_ResetDevice": 4, + "ButtonRequest_ConfirmWord": 5, + "ButtonRequest_WipeDevice": 6, + "ButtonRequest_ProtectCall": 7, + "ButtonRequest_SignTx": 8, + "ButtonRequest_FirmwareCheck": 9, + "ButtonRequest_Address": 10, + "ButtonRequest_PublicKey": 11, + "ButtonRequest_MnemonicWordCount": 12, + "ButtonRequest_MnemonicInput": 13, + "ButtonRequest_PassphraseType": 14, + "ButtonRequest_UnknownDerivationPath": 15, +} + +func (x ButtonRequest_ButtonRequestType) Enum() *ButtonRequest_ButtonRequestType { + p := new(ButtonRequest_ButtonRequestType) + *p = x + return p +} + +func (x ButtonRequest_ButtonRequestType) String() string { + return proto.EnumName(ButtonRequest_ButtonRequestType_name, int32(x)) +} + +func (x *ButtonRequest_ButtonRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ButtonRequest_ButtonRequestType_value, data, "ButtonRequest_ButtonRequestType") + if err != nil { + return err + } + *x = ButtonRequest_ButtonRequestType(value) + return nil +} + +func (ButtonRequest_ButtonRequestType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{2, 0} +} + +//* +// Type of PIN request +type PinMatrixRequest_PinMatrixRequestType int32 + +const ( + PinMatrixRequest_PinMatrixRequestType_Current PinMatrixRequest_PinMatrixRequestType = 1 + PinMatrixRequest_PinMatrixRequestType_NewFirst PinMatrixRequest_PinMatrixRequestType = 2 + PinMatrixRequest_PinMatrixRequestType_NewSecond PinMatrixRequest_PinMatrixRequestType = 3 +) + +var PinMatrixRequest_PinMatrixRequestType_name = map[int32]string{ + 1: "PinMatrixRequestType_Current", + 2: "PinMatrixRequestType_NewFirst", + 3: "PinMatrixRequestType_NewSecond", +} + +var PinMatrixRequest_PinMatrixRequestType_value = map[string]int32{ + "PinMatrixRequestType_Current": 1, + "PinMatrixRequestType_NewFirst": 2, + "PinMatrixRequestType_NewSecond": 3, +} + +func (x PinMatrixRequest_PinMatrixRequestType) Enum() *PinMatrixRequest_PinMatrixRequestType { + p := new(PinMatrixRequest_PinMatrixRequestType) + *p = x + return p +} + +func (x PinMatrixRequest_PinMatrixRequestType) String() string { + return proto.EnumName(PinMatrixRequest_PinMatrixRequestType_name, int32(x)) +} + +func (x *PinMatrixRequest_PinMatrixRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(PinMatrixRequest_PinMatrixRequestType_value, data, "PinMatrixRequest_PinMatrixRequestType") + if err != nil { + return err + } + *x = PinMatrixRequest_PinMatrixRequestType(value) + return nil +} + +func (PinMatrixRequest_PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{4, 0} +} + +//* +// Response: Success of the previous request +// @end +type Success struct { + Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Success) Reset() { *m = Success{} } +func (m *Success) String() string { return proto.CompactTextString(m) } +func (*Success) ProtoMessage() {} +func (*Success) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{0} +} + +func (m *Success) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Success.Unmarshal(m, b) +} +func (m *Success) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Success.Marshal(b, m, deterministic) +} +func (m *Success) XXX_Merge(src proto.Message) { + xxx_messageInfo_Success.Merge(m, src) +} +func (m *Success) XXX_Size() int { + return xxx_messageInfo_Success.Size(m) +} +func (m *Success) XXX_DiscardUnknown() { + xxx_messageInfo_Success.DiscardUnknown(m) +} + +var xxx_messageInfo_Success proto.InternalMessageInfo + +func (m *Success) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +//* +// Response: Failure of the previous request +// @end +type Failure struct { + Code *Failure_FailureType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.Failure_FailureType" json:"code,omitempty"` + Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Failure) Reset() { *m = Failure{} } +func (m *Failure) String() string { return proto.CompactTextString(m) } +func (*Failure) ProtoMessage() {} +func (*Failure) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{1} +} + +func (m *Failure) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Failure.Unmarshal(m, b) +} +func (m *Failure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Failure.Marshal(b, m, deterministic) +} +func (m *Failure) XXX_Merge(src proto.Message) { + xxx_messageInfo_Failure.Merge(m, src) +} +func (m *Failure) XXX_Size() int { + return xxx_messageInfo_Failure.Size(m) +} +func (m *Failure) XXX_DiscardUnknown() { + xxx_messageInfo_Failure.DiscardUnknown(m) +} + +var xxx_messageInfo_Failure proto.InternalMessageInfo + +func (m *Failure) GetCode() Failure_FailureType { + if m != nil && m.Code != nil { + return *m.Code + } + return Failure_Failure_UnexpectedMessage +} + +func (m *Failure) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +//* +// Response: Device is waiting for HW button press. +// @auxstart +// @next ButtonAck +type ButtonRequest struct { + Code *ButtonRequest_ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.ButtonRequest_ButtonRequestType" json:"code,omitempty"` + Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ButtonRequest) Reset() { *m = ButtonRequest{} } +func (m *ButtonRequest) String() string { return proto.CompactTextString(m) } +func (*ButtonRequest) ProtoMessage() {} +func (*ButtonRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{2} +} + +func (m *ButtonRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ButtonRequest.Unmarshal(m, b) +} +func (m *ButtonRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ButtonRequest.Marshal(b, m, deterministic) +} +func (m *ButtonRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ButtonRequest.Merge(m, src) +} +func (m *ButtonRequest) XXX_Size() int { + return xxx_messageInfo_ButtonRequest.Size(m) +} +func (m *ButtonRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ButtonRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ButtonRequest proto.InternalMessageInfo + +func (m *ButtonRequest) GetCode() ButtonRequest_ButtonRequestType { + if m != nil && m.Code != nil { + return *m.Code + } + return ButtonRequest_ButtonRequest_Other +} + +func (m *ButtonRequest) GetData() string { + if m != nil && m.Data != nil { + return *m.Data + } + return "" +} + +//* +// Request: Computer agrees to wait for HW button press +// @auxend +type ButtonAck struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ButtonAck) Reset() { *m = ButtonAck{} } +func (m *ButtonAck) String() string { return proto.CompactTextString(m) } +func (*ButtonAck) ProtoMessage() {} +func (*ButtonAck) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{3} +} + +func (m *ButtonAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ButtonAck.Unmarshal(m, b) +} +func (m *ButtonAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ButtonAck.Marshal(b, m, deterministic) +} +func (m *ButtonAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_ButtonAck.Merge(m, src) +} +func (m *ButtonAck) XXX_Size() int { + return xxx_messageInfo_ButtonAck.Size(m) +} +func (m *ButtonAck) XXX_DiscardUnknown() { + xxx_messageInfo_ButtonAck.DiscardUnknown(m) +} + +var xxx_messageInfo_ButtonAck proto.InternalMessageInfo + +//* +// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme +// @auxstart +// @next PinMatrixAck +type PinMatrixRequest struct { + Type *PinMatrixRequest_PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PinMatrixRequest) Reset() { *m = PinMatrixRequest{} } +func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) } +func (*PinMatrixRequest) ProtoMessage() {} +func (*PinMatrixRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{4} +} + +func (m *PinMatrixRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PinMatrixRequest.Unmarshal(m, b) +} +func (m *PinMatrixRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PinMatrixRequest.Marshal(b, m, deterministic) +} +func (m *PinMatrixRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PinMatrixRequest.Merge(m, src) +} +func (m *PinMatrixRequest) XXX_Size() int { + return xxx_messageInfo_PinMatrixRequest.Size(m) +} +func (m *PinMatrixRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PinMatrixRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PinMatrixRequest proto.InternalMessageInfo + +func (m *PinMatrixRequest) GetType() PinMatrixRequest_PinMatrixRequestType { + if m != nil && m.Type != nil { + return *m.Type + } + return PinMatrixRequest_PinMatrixRequestType_Current +} + +//* +// Request: Computer responds with encoded PIN +// @auxend +type PinMatrixAck struct { + Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PinMatrixAck) Reset() { *m = PinMatrixAck{} } +func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) } +func (*PinMatrixAck) ProtoMessage() {} +func (*PinMatrixAck) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{5} +} + +func (m *PinMatrixAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PinMatrixAck.Unmarshal(m, b) +} +func (m *PinMatrixAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PinMatrixAck.Marshal(b, m, deterministic) +} +func (m *PinMatrixAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_PinMatrixAck.Merge(m, src) +} +func (m *PinMatrixAck) XXX_Size() int { + return xxx_messageInfo_PinMatrixAck.Size(m) +} +func (m *PinMatrixAck) XXX_DiscardUnknown() { + xxx_messageInfo_PinMatrixAck.DiscardUnknown(m) +} + +var xxx_messageInfo_PinMatrixAck proto.InternalMessageInfo + +func (m *PinMatrixAck) GetPin() string { + if m != nil && m.Pin != nil { + return *m.Pin + } + return "" +} + +//* +// Response: Device awaits encryption passphrase +// @auxstart +// @next PassphraseAck +type PassphraseRequest struct { + OnDevice *bool `protobuf:"varint,1,opt,name=on_device,json=onDevice" json:"on_device,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PassphraseRequest) Reset() { *m = PassphraseRequest{} } +func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) } +func (*PassphraseRequest) ProtoMessage() {} +func (*PassphraseRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{6} +} + +func (m *PassphraseRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PassphraseRequest.Unmarshal(m, b) +} +func (m *PassphraseRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PassphraseRequest.Marshal(b, m, deterministic) +} +func (m *PassphraseRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PassphraseRequest.Merge(m, src) +} +func (m *PassphraseRequest) XXX_Size() int { + return xxx_messageInfo_PassphraseRequest.Size(m) +} +func (m *PassphraseRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PassphraseRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PassphraseRequest proto.InternalMessageInfo + +func (m *PassphraseRequest) GetOnDevice() bool { + if m != nil && m.OnDevice != nil { + return *m.OnDevice + } + return false +} + +//* +// Request: Send passphrase back +// @next PassphraseStateRequest +type PassphraseAck struct { + Passphrase *string `protobuf:"bytes,1,opt,name=passphrase" json:"passphrase,omitempty"` + State []byte `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PassphraseAck) Reset() { *m = PassphraseAck{} } +func (m *PassphraseAck) String() string { return proto.CompactTextString(m) } +func (*PassphraseAck) ProtoMessage() {} +func (*PassphraseAck) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{7} +} + +func (m *PassphraseAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PassphraseAck.Unmarshal(m, b) +} +func (m *PassphraseAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PassphraseAck.Marshal(b, m, deterministic) +} +func (m *PassphraseAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_PassphraseAck.Merge(m, src) +} +func (m *PassphraseAck) XXX_Size() int { + return xxx_messageInfo_PassphraseAck.Size(m) +} +func (m *PassphraseAck) XXX_DiscardUnknown() { + xxx_messageInfo_PassphraseAck.DiscardUnknown(m) +} + +var xxx_messageInfo_PassphraseAck proto.InternalMessageInfo + +func (m *PassphraseAck) GetPassphrase() string { + if m != nil && m.Passphrase != nil { + return *m.Passphrase + } + return "" +} + +func (m *PassphraseAck) GetState() []byte { + if m != nil { + return m.State + } + return nil +} + +//* +// Response: Device awaits passphrase state +// @next PassphraseStateAck +type PassphraseStateRequest struct { + State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PassphraseStateRequest) Reset() { *m = PassphraseStateRequest{} } +func (m *PassphraseStateRequest) String() string { return proto.CompactTextString(m) } +func (*PassphraseStateRequest) ProtoMessage() {} +func (*PassphraseStateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{8} +} + +func (m *PassphraseStateRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PassphraseStateRequest.Unmarshal(m, b) +} +func (m *PassphraseStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PassphraseStateRequest.Marshal(b, m, deterministic) +} +func (m *PassphraseStateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PassphraseStateRequest.Merge(m, src) +} +func (m *PassphraseStateRequest) XXX_Size() int { + return xxx_messageInfo_PassphraseStateRequest.Size(m) +} +func (m *PassphraseStateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PassphraseStateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PassphraseStateRequest proto.InternalMessageInfo + +func (m *PassphraseStateRequest) GetState() []byte { + if m != nil { + return m.State + } + return nil +} + +//* +// Request: Send passphrase state back +// @auxend +type PassphraseStateAck struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PassphraseStateAck) Reset() { *m = PassphraseStateAck{} } +func (m *PassphraseStateAck) String() string { return proto.CompactTextString(m) } +func (*PassphraseStateAck) ProtoMessage() {} +func (*PassphraseStateAck) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{9} +} + +func (m *PassphraseStateAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PassphraseStateAck.Unmarshal(m, b) +} +func (m *PassphraseStateAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PassphraseStateAck.Marshal(b, m, deterministic) +} +func (m *PassphraseStateAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_PassphraseStateAck.Merge(m, src) +} +func (m *PassphraseStateAck) XXX_Size() int { + return xxx_messageInfo_PassphraseStateAck.Size(m) +} +func (m *PassphraseStateAck) XXX_DiscardUnknown() { + xxx_messageInfo_PassphraseStateAck.DiscardUnknown(m) +} + +var xxx_messageInfo_PassphraseStateAck proto.InternalMessageInfo + +//* +// Structure representing BIP32 (hierarchical deterministic) node +// Used for imports of private key into the device and exporting public key out of device +// @embed +type HDNodeType struct { + Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"` + Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"` + ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"` + ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"` + PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"` + PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HDNodeType) Reset() { *m = HDNodeType{} } +func (m *HDNodeType) String() string { return proto.CompactTextString(m) } +func (*HDNodeType) ProtoMessage() {} +func (*HDNodeType) Descriptor() ([]byte, []int) { + return fileDescriptor_aaf30d059fdbc38d, []int{10} +} + +func (m *HDNodeType) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HDNodeType.Unmarshal(m, b) +} +func (m *HDNodeType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HDNodeType.Marshal(b, m, deterministic) +} +func (m *HDNodeType) XXX_Merge(src proto.Message) { + xxx_messageInfo_HDNodeType.Merge(m, src) +} +func (m *HDNodeType) XXX_Size() int { + return xxx_messageInfo_HDNodeType.Size(m) +} +func (m *HDNodeType) XXX_DiscardUnknown() { + xxx_messageInfo_HDNodeType.DiscardUnknown(m) +} + +var xxx_messageInfo_HDNodeType proto.InternalMessageInfo + +func (m *HDNodeType) GetDepth() uint32 { + if m != nil && m.Depth != nil { + return *m.Depth + } + return 0 +} + +func (m *HDNodeType) GetFingerprint() uint32 { + if m != nil && m.Fingerprint != nil { + return *m.Fingerprint + } + return 0 +} + +func (m *HDNodeType) GetChildNum() uint32 { + if m != nil && m.ChildNum != nil { + return *m.ChildNum + } + return 0 +} + +func (m *HDNodeType) GetChainCode() []byte { + if m != nil { + return m.ChainCode + } + return nil +} + +func (m *HDNodeType) GetPrivateKey() []byte { + if m != nil { + return m.PrivateKey + } + return nil +} + +func (m *HDNodeType) GetPublicKey() []byte { + if m != nil { + return m.PublicKey + } + return nil +} + +func init() { + proto.RegisterEnum("hw.trezor.messages.common.Failure_FailureType", Failure_FailureType_name, Failure_FailureType_value) + proto.RegisterEnum("hw.trezor.messages.common.ButtonRequest_ButtonRequestType", ButtonRequest_ButtonRequestType_name, ButtonRequest_ButtonRequestType_value) + proto.RegisterEnum("hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType", PinMatrixRequest_PinMatrixRequestType_name, PinMatrixRequest_PinMatrixRequestType_value) + proto.RegisterType((*Success)(nil), "hw.trezor.messages.common.Success") + proto.RegisterType((*Failure)(nil), "hw.trezor.messages.common.Failure") + proto.RegisterType((*ButtonRequest)(nil), "hw.trezor.messages.common.ButtonRequest") + proto.RegisterType((*ButtonAck)(nil), "hw.trezor.messages.common.ButtonAck") + proto.RegisterType((*PinMatrixRequest)(nil), "hw.trezor.messages.common.PinMatrixRequest") + proto.RegisterType((*PinMatrixAck)(nil), "hw.trezor.messages.common.PinMatrixAck") + proto.RegisterType((*PassphraseRequest)(nil), "hw.trezor.messages.common.PassphraseRequest") + proto.RegisterType((*PassphraseAck)(nil), "hw.trezor.messages.common.PassphraseAck") + proto.RegisterType((*PassphraseStateRequest)(nil), "hw.trezor.messages.common.PassphraseStateRequest") + proto.RegisterType((*PassphraseStateAck)(nil), "hw.trezor.messages.common.PassphraseStateAck") + proto.RegisterType((*HDNodeType)(nil), "hw.trezor.messages.common.HDNodeType") +} + +func init() { proto.RegisterFile("messages-common.proto", fileDescriptor_aaf30d059fdbc38d) } + +var fileDescriptor_aaf30d059fdbc38d = []byte{ + // 846 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xcd, 0x52, 0x23, 0x37, + 0x10, 0x2e, 0xff, 0x80, 0xed, 0xb6, 0xd9, 0x08, 0xc5, 0x80, 0x09, 0xb0, 0x38, 0xc3, 0x21, 0x5c, + 0xe2, 0x4a, 0xe5, 0x98, 0x53, 0x58, 0x83, 0x2b, 0xd4, 0x16, 0x86, 0x1a, 0xd8, 0xda, 0xa3, 0x4b, + 0xd1, 0xf4, 0x32, 0x2a, 0xcf, 0x48, 0x13, 0x8d, 0x06, 0xf0, 0x5e, 0xf2, 0x6a, 0x79, 0x89, 0xbc, + 0x42, 0xaa, 0x52, 0xb9, 0xe4, 0x11, 0xb6, 0x34, 0x3f, 0x78, 0xc6, 0x66, 0x39, 0xcd, 0xe8, 0xfb, + 0xbe, 0xee, 0x96, 0xba, 0x3f, 0x09, 0x76, 0x42, 0x8c, 0x63, 0x76, 0x8f, 0xf1, 0x8f, 0x5c, 0x85, + 0xa1, 0x92, 0xa3, 0x48, 0x2b, 0xa3, 0xe8, 0xbe, 0xff, 0x38, 0x32, 0x1a, 0x3f, 0x2b, 0x3d, 0x2a, + 0x04, 0xa3, 0x4c, 0xe0, 0x9c, 0x40, 0xeb, 0x36, 0xe1, 0x1c, 0xe3, 0x98, 0x0e, 0xa0, 0x95, 0xb3, + 0x83, 0xda, 0xb0, 0x76, 0xda, 0x71, 0x8b, 0xa5, 0xf3, 0x77, 0x03, 0x5a, 0x13, 0x26, 0x82, 0x44, + 0x23, 0x7d, 0x07, 0x4d, 0xae, 0xbc, 0x4c, 0xf2, 0xe6, 0xe7, 0xd1, 0xe8, 0xab, 0xa9, 0x47, 0x79, + 0x44, 0xf1, 0xbd, 0x5b, 0x44, 0xe8, 0xa6, 0xb1, 0xe5, 0x4a, 0xf5, 0x6a, 0xa5, 0xff, 0xea, 0xd0, + 0x2d, 0xe9, 0xe9, 0x11, 0xec, 0xe7, 0xcb, 0xd9, 0x07, 0x89, 0x4f, 0x11, 0x72, 0x83, 0xde, 0x55, + 0x26, 0x26, 0x35, 0xfa, 0x1d, 0xec, 0x16, 0xf4, 0xbb, 0xc4, 0x18, 0x25, 0x2f, 0x72, 0x09, 0xa9, + 0xd3, 0x1d, 0xd8, 0x2e, 0xb8, 0x73, 0x66, 0xd8, 0x85, 0xd6, 0x4a, 0x93, 0x06, 0x3d, 0x80, 0xbd, + 0x02, 0x3e, 0xe3, 0x46, 0x28, 0x39, 0x66, 0x92, 0x63, 0x10, 0xa0, 0x47, 0x9a, 0x74, 0x0f, 0xbe, + 0x2d, 0xc8, 0x1b, 0xb1, 0x4c, 0xb6, 0x41, 0x07, 0xd0, 0x2f, 0x11, 0xcb, 0x90, 0x4d, 0xba, 0x0b, + 0xb4, 0xc4, 0x5c, 0xca, 0x07, 0x16, 0x08, 0x8f, 0xb4, 0xe8, 0x21, 0x0c, 0x0a, 0x3c, 0x07, 0x6f, + 0xc5, 0xbd, 0x64, 0x26, 0xd1, 0x48, 0xda, 0x95, 0x7c, 0x5a, 0xd9, 0xf6, 0x67, 0xfb, 0xeb, 0x94, + 0x8f, 0x34, 0x55, 0xe6, 0x42, 0xaa, 0xe4, 0xde, 0x9f, 0x24, 0xd2, 0x8b, 0x09, 0xac, 0x70, 0x97, + 0x52, 0x18, 0xc1, 0x02, 0xf1, 0x19, 0x3d, 0xd2, 0x5d, 0xd9, 0xfa, 0x95, 0x88, 0x43, 0x66, 0xb8, + 0x4f, 0x7a, 0x74, 0x1f, 0x76, 0x0a, 0x62, 0x22, 0x74, 0xf8, 0xc8, 0x34, 0x66, 0xb5, 0xb8, 0xf3, + 0x4f, 0x13, 0xb6, 0xb2, 0xbe, 0xb9, 0xf8, 0x47, 0x82, 0xb1, 0xa1, 0xd3, 0xca, 0x74, 0x7f, 0x79, + 0x65, 0xba, 0x95, 0xb8, 0xea, 0xaa, 0x34, 0x69, 0x0a, 0x4d, 0x8f, 0x19, 0x96, 0x8f, 0x39, 0xfd, + 0x77, 0xfe, 0x6f, 0xc0, 0xf6, 0x9a, 0xde, 0xee, 0xbf, 0x02, 0xce, 0xae, 0x8d, 0x8f, 0x9a, 0xd4, + 0xa8, 0x03, 0x6f, 0xab, 0xc4, 0x04, 0xf1, 0xfa, 0x01, 0xf5, 0x9d, 0xaf, 0x31, 0xf6, 0x55, 0x60, + 0x67, 0x7d, 0x0c, 0x07, 0x55, 0xcd, 0x58, 0xc9, 0x4f, 0x42, 0x87, 0xd7, 0x89, 0x89, 0x12, 0x43, + 0x1a, 0xd6, 0x47, 0x55, 0x81, 0x8b, 0x31, 0x9a, 0x73, 0x7c, 0x10, 0x1c, 0x49, 0x73, 0x9d, 0xce, + 0xe3, 0x3f, 0x2a, 0x6d, 0xa7, 0x7f, 0x08, 0x83, 0x2a, 0xfd, 0x51, 0x44, 0x98, 0x07, 0x6f, 0xae, + 0x07, 0xdf, 0x68, 0x65, 0x90, 0x9b, 0x31, 0x0b, 0x02, 0xd2, 0xb2, 0xa3, 0xae, 0xd2, 0xd6, 0x07, + 0x77, 0x4f, 0xa4, 0xbd, 0xbe, 0xeb, 0x62, 0x3e, 0x63, 0x1f, 0xf9, 0x9c, 0x74, 0xec, 0xe8, 0xaa, + 0x82, 0x33, 0xcf, 0xd3, 0x18, 0x5b, 0x2b, 0x1c, 0xc0, 0xde, 0x4a, 0xd1, 0xe4, 0xf7, 0x40, 0xf0, + 0xf7, 0xb8, 0x20, 0x5d, 0x7a, 0x02, 0xc7, 0x55, 0xf2, 0x4a, 0x62, 0xa8, 0xa4, 0xe0, 0xf6, 0x3c, + 0x63, 0x95, 0x48, 0x43, 0x7a, 0xeb, 0xd5, 0x0b, 0xd1, 0xa5, 0xb4, 0x3d, 0xdb, 0xa2, 0x43, 0x38, + 0x5c, 0x29, 0xc1, 0xe2, 0x38, 0xf2, 0x35, 0x8b, 0xd3, 0xbb, 0x49, 0xde, 0xd0, 0x1f, 0xe0, 0xa4, + 0xaa, 0xf8, 0x20, 0xe7, 0x52, 0x3d, 0xca, 0x73, 0xd4, 0xe2, 0x81, 0xd9, 0xcb, 0x75, 0xc3, 0x8c, + 0x4f, 0xbe, 0x71, 0xba, 0xd0, 0xc9, 0x84, 0x67, 0x7c, 0xee, 0xfc, 0x5b, 0x03, 0x62, 0x2d, 0xca, + 0x8c, 0x16, 0x4f, 0x85, 0xf1, 0xee, 0xa0, 0x69, 0x16, 0x51, 0x61, 0xbc, 0x5f, 0x5f, 0x31, 0xde, + 0x6a, 0xe8, 0x1a, 0x90, 0xd9, 0xcf, 0x66, 0x73, 0xfe, 0x84, 0xfe, 0x4b, 0xac, 0x3d, 0xda, 0x4b, + 0xf8, 0x6c, 0x9c, 0x68, 0x8d, 0xd2, 0x90, 0x1a, 0xfd, 0x1e, 0x8e, 0x5e, 0x54, 0x4c, 0xf1, 0x71, + 0x22, 0x74, 0x6c, 0x48, 0xdd, 0x1a, 0xf3, 0x6b, 0x92, 0x5b, 0xe4, 0x4a, 0x7a, 0xa4, 0xe1, 0x0c, + 0xa1, 0xf7, 0xac, 0x39, 0xe3, 0x73, 0x4a, 0xa0, 0x11, 0x09, 0x39, 0xa8, 0x0d, 0xeb, 0xa7, 0x1d, + 0xd7, 0xfe, 0x3a, 0x3f, 0xc1, 0xf6, 0xb2, 0xaf, 0x45, 0x37, 0x0e, 0xa0, 0xa3, 0xe4, 0xcc, 0x4b, + 0x1d, 0x96, 0xb6, 0xa4, 0xed, 0xb6, 0x95, 0xcc, 0x1c, 0xe7, 0x5c, 0xc0, 0xd6, 0x32, 0xc2, 0x26, + 0x7d, 0x0b, 0x10, 0x3d, 0x03, 0xf9, 0xdb, 0x5d, 0x42, 0x68, 0x1f, 0x36, 0x62, 0xc3, 0x4c, 0xf6, + 0xd8, 0xf6, 0xdc, 0x6c, 0xe1, 0x8c, 0x60, 0x77, 0x99, 0xe6, 0xd6, 0x42, 0x45, 0xf5, 0x67, 0x7d, + 0xad, 0xac, 0xef, 0x03, 0x5d, 0xd1, 0xdb, 0x61, 0xfe, 0x55, 0x03, 0xf8, 0xed, 0x7c, 0xaa, 0xbc, + 0xec, 0xbd, 0xee, 0xc3, 0x86, 0x87, 0x91, 0xf1, 0xd3, 0x13, 0x6e, 0xb9, 0xd9, 0x82, 0x0e, 0xa1, + 0xfb, 0x49, 0xc8, 0x7b, 0xd4, 0x91, 0x16, 0xd2, 0x0c, 0xea, 0x29, 0x57, 0x86, 0xec, 0x81, 0xb9, + 0x2f, 0x02, 0x6f, 0x26, 0x93, 0x70, 0xd0, 0x48, 0xf9, 0x76, 0x0a, 0x4c, 0x93, 0x90, 0x1e, 0x01, + 0x70, 0x9f, 0x09, 0x39, 0x4b, 0x9f, 0xa6, 0xe6, 0xb0, 0x7e, 0xda, 0x73, 0x3b, 0x29, 0x32, 0xb6, + 0x6f, 0xcc, 0x31, 0x74, 0xa3, 0xd4, 0x6f, 0x38, 0x9b, 0xe3, 0x62, 0xb0, 0x91, 0x6e, 0x1a, 0x72, + 0xe8, 0x3d, 0x2e, 0x6c, 0x7c, 0x94, 0xde, 0x8e, 0x94, 0xdf, 0x4c, 0xf9, 0x4e, 0x54, 0xdc, 0x97, + 0x2f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x7d, 0x20, 0xa6, 0x35, 0x07, 0x00, 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.proto new file mode 100644 index 000000000..75a983b0a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-common.proto @@ -0,0 +1,147 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto +// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. + +syntax = "proto2"; +package hw.trezor.messages.common; + +/** + * Response: Success of the previous request + * @end + */ +message Success { + optional string message = 1; // human readable description of action or request-specific payload +} + +/** + * Response: Failure of the previous request + * @end + */ +message Failure { + optional FailureType code = 1; // computer-readable definition of the error state + optional string message = 2; // human-readable message of the error state + enum FailureType { + Failure_UnexpectedMessage = 1; + Failure_ButtonExpected = 2; + Failure_DataError = 3; + Failure_ActionCancelled = 4; + Failure_PinExpected = 5; + Failure_PinCancelled = 6; + Failure_PinInvalid = 7; + Failure_InvalidSignature = 8; + Failure_ProcessError = 9; + Failure_NotEnoughFunds = 10; + Failure_NotInitialized = 11; + Failure_PinMismatch = 12; + Failure_FirmwareError = 99; + } +} + +/** + * Response: Device is waiting for HW button press. + * @auxstart + * @next ButtonAck + */ +message ButtonRequest { + optional ButtonRequestType code = 1; + optional string data = 2; + /** + * Type of button request + */ + enum ButtonRequestType { + ButtonRequest_Other = 1; + ButtonRequest_FeeOverThreshold = 2; + ButtonRequest_ConfirmOutput = 3; + ButtonRequest_ResetDevice = 4; + ButtonRequest_ConfirmWord = 5; + ButtonRequest_WipeDevice = 6; + ButtonRequest_ProtectCall = 7; + ButtonRequest_SignTx = 8; + ButtonRequest_FirmwareCheck = 9; + ButtonRequest_Address = 10; + ButtonRequest_PublicKey = 11; + ButtonRequest_MnemonicWordCount = 12; + ButtonRequest_MnemonicInput = 13; + ButtonRequest_PassphraseType = 14; + ButtonRequest_UnknownDerivationPath = 15; + } +} + +/** + * Request: Computer agrees to wait for HW button press + * @auxend + */ +message ButtonAck { +} + +/** + * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme + * @auxstart + * @next PinMatrixAck + */ +message PinMatrixRequest { + optional PinMatrixRequestType type = 1; + /** + * Type of PIN request + */ + enum PinMatrixRequestType { + PinMatrixRequestType_Current = 1; + PinMatrixRequestType_NewFirst = 2; + PinMatrixRequestType_NewSecond = 3; + } +} + +/** + * Request: Computer responds with encoded PIN + * @auxend + */ +message PinMatrixAck { + required string pin = 1; // matrix encoded PIN entered by user +} + +/** + * Response: Device awaits encryption passphrase + * @auxstart + * @next PassphraseAck + */ +message PassphraseRequest { + optional bool on_device = 1; // passphrase is being entered on the device +} + +/** + * Request: Send passphrase back + * @next PassphraseStateRequest + */ +message PassphraseAck { + optional string passphrase = 1; + optional bytes state = 2; // expected device state +} + +/** + * Response: Device awaits passphrase state + * @next PassphraseStateAck + */ +message PassphraseStateRequest { + optional bytes state = 1; // actual device state +} + +/** + * Request: Send passphrase state back + * @auxend + */ +message PassphraseStateAck { +} + +/** + * Structure representing BIP32 (hierarchical deterministic) node + * Used for imports of private key into the device and exporting public key out of device + * @embed + */ +message HDNodeType { + required uint32 depth = 1; + required uint32 fingerprint = 2; + required uint32 child_num = 3; + required bytes chain_code = 4; + optional bytes private_key = 5; + optional bytes public_key = 6; +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.pb.go new file mode 100644 index 000000000..5d664f5ba --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.pb.go @@ -0,0 +1,698 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages-ethereum.proto + +package trezor + +import ( + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +//* +// Request: Ask device for public key corresponding to address_n path +// @start +// @next EthereumPublicKey +// @next Failure +type EthereumGetPublicKey struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumGetPublicKey) Reset() { *m = EthereumGetPublicKey{} } +func (m *EthereumGetPublicKey) String() string { return proto.CompactTextString(m) } +func (*EthereumGetPublicKey) ProtoMessage() {} +func (*EthereumGetPublicKey) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{0} +} + +func (m *EthereumGetPublicKey) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumGetPublicKey.Unmarshal(m, b) +} +func (m *EthereumGetPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumGetPublicKey.Marshal(b, m, deterministic) +} +func (m *EthereumGetPublicKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumGetPublicKey.Merge(m, src) +} +func (m *EthereumGetPublicKey) XXX_Size() int { + return xxx_messageInfo_EthereumGetPublicKey.Size(m) +} +func (m *EthereumGetPublicKey) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumGetPublicKey.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumGetPublicKey proto.InternalMessageInfo + +func (m *EthereumGetPublicKey) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumGetPublicKey) GetShowDisplay() bool { + if m != nil && m.ShowDisplay != nil { + return *m.ShowDisplay + } + return false +} + +//* +// Response: Contains public key derived from device private seed +// @end +type EthereumPublicKey struct { + Node *HDNodeType `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"` + Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumPublicKey) Reset() { *m = EthereumPublicKey{} } +func (m *EthereumPublicKey) String() string { return proto.CompactTextString(m) } +func (*EthereumPublicKey) ProtoMessage() {} +func (*EthereumPublicKey) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{1} +} + +func (m *EthereumPublicKey) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumPublicKey.Unmarshal(m, b) +} +func (m *EthereumPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumPublicKey.Marshal(b, m, deterministic) +} +func (m *EthereumPublicKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumPublicKey.Merge(m, src) +} +func (m *EthereumPublicKey) XXX_Size() int { + return xxx_messageInfo_EthereumPublicKey.Size(m) +} +func (m *EthereumPublicKey) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumPublicKey.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumPublicKey proto.InternalMessageInfo + +func (m *EthereumPublicKey) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *EthereumPublicKey) GetXpub() string { + if m != nil && m.Xpub != nil { + return *m.Xpub + } + return "" +} + +//* +// Request: Ask device for Ethereum address corresponding to address_n path +// @start +// @next EthereumAddress +// @next Failure +type EthereumGetAddress struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumGetAddress) Reset() { *m = EthereumGetAddress{} } +func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) } +func (*EthereumGetAddress) ProtoMessage() {} +func (*EthereumGetAddress) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{2} +} + +func (m *EthereumGetAddress) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumGetAddress.Unmarshal(m, b) +} +func (m *EthereumGetAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumGetAddress.Marshal(b, m, deterministic) +} +func (m *EthereumGetAddress) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumGetAddress.Merge(m, src) +} +func (m *EthereumGetAddress) XXX_Size() int { + return xxx_messageInfo_EthereumGetAddress.Size(m) +} +func (m *EthereumGetAddress) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumGetAddress.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumGetAddress proto.InternalMessageInfo + +func (m *EthereumGetAddress) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumGetAddress) GetShowDisplay() bool { + if m != nil && m.ShowDisplay != nil { + return *m.ShowDisplay + } + return false +} + +//* +// Response: Contains an Ethereum address derived from device private seed +// @end +type EthereumAddress struct { + AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` + AddressHex *string `protobuf:"bytes,2,opt,name=addressHex" json:"addressHex,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumAddress) Reset() { *m = EthereumAddress{} } +func (m *EthereumAddress) String() string { return proto.CompactTextString(m) } +func (*EthereumAddress) ProtoMessage() {} +func (*EthereumAddress) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{3} +} + +func (m *EthereumAddress) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumAddress.Unmarshal(m, b) +} +func (m *EthereumAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumAddress.Marshal(b, m, deterministic) +} +func (m *EthereumAddress) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumAddress.Merge(m, src) +} +func (m *EthereumAddress) XXX_Size() int { + return xxx_messageInfo_EthereumAddress.Size(m) +} +func (m *EthereumAddress) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumAddress.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumAddress proto.InternalMessageInfo + +func (m *EthereumAddress) GetAddressBin() []byte { + if m != nil { + return m.AddressBin + } + return nil +} + +func (m *EthereumAddress) GetAddressHex() string { + if m != nil && m.AddressHex != nil { + return *m.AddressHex + } + return "" +} + +//* +// Request: Ask device to sign transaction +// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. +// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. +// @start +// @next EthereumTxRequest +// @next Failure +type EthereumSignTx struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` + GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` + GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` + ToBin []byte `protobuf:"bytes,5,opt,name=toBin" json:"toBin,omitempty"` + ToHex *string `protobuf:"bytes,11,opt,name=toHex" json:"toHex,omitempty"` + Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` + DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` + DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` + ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` + TxType *uint32 `protobuf:"varint,10,opt,name=tx_type,json=txType" json:"tx_type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumSignTx) Reset() { *m = EthereumSignTx{} } +func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) } +func (*EthereumSignTx) ProtoMessage() {} +func (*EthereumSignTx) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{4} +} + +func (m *EthereumSignTx) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumSignTx.Unmarshal(m, b) +} +func (m *EthereumSignTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumSignTx.Marshal(b, m, deterministic) +} +func (m *EthereumSignTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumSignTx.Merge(m, src) +} +func (m *EthereumSignTx) XXX_Size() int { + return xxx_messageInfo_EthereumSignTx.Size(m) +} +func (m *EthereumSignTx) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumSignTx.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumSignTx proto.InternalMessageInfo + +func (m *EthereumSignTx) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumSignTx) GetNonce() []byte { + if m != nil { + return m.Nonce + } + return nil +} + +func (m *EthereumSignTx) GetGasPrice() []byte { + if m != nil { + return m.GasPrice + } + return nil +} + +func (m *EthereumSignTx) GetGasLimit() []byte { + if m != nil { + return m.GasLimit + } + return nil +} + +func (m *EthereumSignTx) GetToBin() []byte { + if m != nil { + return m.ToBin + } + return nil +} + +func (m *EthereumSignTx) GetToHex() string { + if m != nil && m.ToHex != nil { + return *m.ToHex + } + return "" +} + +func (m *EthereumSignTx) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *EthereumSignTx) GetDataInitialChunk() []byte { + if m != nil { + return m.DataInitialChunk + } + return nil +} + +func (m *EthereumSignTx) GetDataLength() uint32 { + if m != nil && m.DataLength != nil { + return *m.DataLength + } + return 0 +} + +func (m *EthereumSignTx) GetChainId() uint32 { + if m != nil && m.ChainId != nil { + return *m.ChainId + } + return 0 +} + +func (m *EthereumSignTx) GetTxType() uint32 { + if m != nil && m.TxType != nil { + return *m.TxType + } + return 0 +} + +//* +// Response: Device asks for more data from transaction payload, or returns the signature. +// If data_length is set, device awaits that many more bytes of payload. +// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. +// @end +// @next EthereumTxAck +type EthereumTxRequest struct { + DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` + SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` + SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` + SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumTxRequest) Reset() { *m = EthereumTxRequest{} } +func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) } +func (*EthereumTxRequest) ProtoMessage() {} +func (*EthereumTxRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{5} +} + +func (m *EthereumTxRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumTxRequest.Unmarshal(m, b) +} +func (m *EthereumTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumTxRequest.Marshal(b, m, deterministic) +} +func (m *EthereumTxRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumTxRequest.Merge(m, src) +} +func (m *EthereumTxRequest) XXX_Size() int { + return xxx_messageInfo_EthereumTxRequest.Size(m) +} +func (m *EthereumTxRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumTxRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumTxRequest proto.InternalMessageInfo + +func (m *EthereumTxRequest) GetDataLength() uint32 { + if m != nil && m.DataLength != nil { + return *m.DataLength + } + return 0 +} + +func (m *EthereumTxRequest) GetSignatureV() uint32 { + if m != nil && m.SignatureV != nil { + return *m.SignatureV + } + return 0 +} + +func (m *EthereumTxRequest) GetSignatureR() []byte { + if m != nil { + return m.SignatureR + } + return nil +} + +func (m *EthereumTxRequest) GetSignatureS() []byte { + if m != nil { + return m.SignatureS + } + return nil +} + +//* +// Request: Transaction payload data. +// @next EthereumTxRequest +type EthereumTxAck struct { + DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumTxAck) Reset() { *m = EthereumTxAck{} } +func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) } +func (*EthereumTxAck) ProtoMessage() {} +func (*EthereumTxAck) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{6} +} + +func (m *EthereumTxAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumTxAck.Unmarshal(m, b) +} +func (m *EthereumTxAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumTxAck.Marshal(b, m, deterministic) +} +func (m *EthereumTxAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumTxAck.Merge(m, src) +} +func (m *EthereumTxAck) XXX_Size() int { + return xxx_messageInfo_EthereumTxAck.Size(m) +} +func (m *EthereumTxAck) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumTxAck.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumTxAck proto.InternalMessageInfo + +func (m *EthereumTxAck) GetDataChunk() []byte { + if m != nil { + return m.DataChunk + } + return nil +} + +//* +// Request: Ask device to sign message +// @start +// @next EthereumMessageSignature +// @next Failure +type EthereumSignMessage struct { + AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` + Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumSignMessage) Reset() { *m = EthereumSignMessage{} } +func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) } +func (*EthereumSignMessage) ProtoMessage() {} +func (*EthereumSignMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{7} +} + +func (m *EthereumSignMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumSignMessage.Unmarshal(m, b) +} +func (m *EthereumSignMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumSignMessage.Marshal(b, m, deterministic) +} +func (m *EthereumSignMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumSignMessage.Merge(m, src) +} +func (m *EthereumSignMessage) XXX_Size() int { + return xxx_messageInfo_EthereumSignMessage.Size(m) +} +func (m *EthereumSignMessage) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumSignMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumSignMessage proto.InternalMessageInfo + +func (m *EthereumSignMessage) GetAddressN() []uint32 { + if m != nil { + return m.AddressN + } + return nil +} + +func (m *EthereumSignMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +//* +// Response: Signed message +// @end +type EthereumMessageSignature struct { + AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + AddressHex *string `protobuf:"bytes,3,opt,name=addressHex" json:"addressHex,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumMessageSignature) Reset() { *m = EthereumMessageSignature{} } +func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) } +func (*EthereumMessageSignature) ProtoMessage() {} +func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{8} +} + +func (m *EthereumMessageSignature) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumMessageSignature.Unmarshal(m, b) +} +func (m *EthereumMessageSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumMessageSignature.Marshal(b, m, deterministic) +} +func (m *EthereumMessageSignature) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumMessageSignature.Merge(m, src) +} +func (m *EthereumMessageSignature) XXX_Size() int { + return xxx_messageInfo_EthereumMessageSignature.Size(m) +} +func (m *EthereumMessageSignature) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumMessageSignature.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumMessageSignature proto.InternalMessageInfo + +func (m *EthereumMessageSignature) GetAddressBin() []byte { + if m != nil { + return m.AddressBin + } + return nil +} + +func (m *EthereumMessageSignature) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *EthereumMessageSignature) GetAddressHex() string { + if m != nil && m.AddressHex != nil { + return *m.AddressHex + } + return "" +} + +//* +// Request: Ask device to verify message +// @start +// @next Success +// @next Failure +type EthereumVerifyMessage struct { + AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` + AddressHex *string `protobuf:"bytes,4,opt,name=addressHex" json:"addressHex,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EthereumVerifyMessage) Reset() { *m = EthereumVerifyMessage{} } +func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) } +func (*EthereumVerifyMessage) ProtoMessage() {} +func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_cb33f46ba915f15c, []int{9} +} + +func (m *EthereumVerifyMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EthereumVerifyMessage.Unmarshal(m, b) +} +func (m *EthereumVerifyMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EthereumVerifyMessage.Marshal(b, m, deterministic) +} +func (m *EthereumVerifyMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_EthereumVerifyMessage.Merge(m, src) +} +func (m *EthereumVerifyMessage) XXX_Size() int { + return xxx_messageInfo_EthereumVerifyMessage.Size(m) +} +func (m *EthereumVerifyMessage) XXX_DiscardUnknown() { + xxx_messageInfo_EthereumVerifyMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_EthereumVerifyMessage proto.InternalMessageInfo + +func (m *EthereumVerifyMessage) GetAddressBin() []byte { + if m != nil { + return m.AddressBin + } + return nil +} + +func (m *EthereumVerifyMessage) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *EthereumVerifyMessage) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +func (m *EthereumVerifyMessage) GetAddressHex() string { + if m != nil && m.AddressHex != nil { + return *m.AddressHex + } + return "" +} + +func init() { + proto.RegisterType((*EthereumGetPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumGetPublicKey") + proto.RegisterType((*EthereumPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumPublicKey") + proto.RegisterType((*EthereumGetAddress)(nil), "hw.trezor.messages.ethereum.EthereumGetAddress") + proto.RegisterType((*EthereumAddress)(nil), "hw.trezor.messages.ethereum.EthereumAddress") + proto.RegisterType((*EthereumSignTx)(nil), "hw.trezor.messages.ethereum.EthereumSignTx") + proto.RegisterType((*EthereumTxRequest)(nil), "hw.trezor.messages.ethereum.EthereumTxRequest") + proto.RegisterType((*EthereumTxAck)(nil), "hw.trezor.messages.ethereum.EthereumTxAck") + proto.RegisterType((*EthereumSignMessage)(nil), "hw.trezor.messages.ethereum.EthereumSignMessage") + proto.RegisterType((*EthereumMessageSignature)(nil), "hw.trezor.messages.ethereum.EthereumMessageSignature") + proto.RegisterType((*EthereumVerifyMessage)(nil), "hw.trezor.messages.ethereum.EthereumVerifyMessage") +} + +func init() { proto.RegisterFile("messages-ethereum.proto", fileDescriptor_cb33f46ba915f15c) } + +var fileDescriptor_cb33f46ba915f15c = []byte{ + // 593 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x95, 0x9b, 0xb4, 0x49, 0x26, 0x0d, 0x1f, 0xa6, 0x55, 0x17, 0x0a, 0x34, 0x18, 0x21, 0xe5, + 0x00, 0x3e, 0x70, 0x43, 0xe2, 0xd2, 0x52, 0x44, 0x2b, 0x4a, 0x55, 0xdc, 0xa8, 0x57, 0x6b, 0x63, + 0x6f, 0xe3, 0x55, 0x9d, 0xdd, 0xe0, 0x5d, 0xb7, 0x0e, 0x7f, 0x82, 0x23, 0xff, 0x87, 0x5f, 0x86, + 0xf6, 0x2b, 0x71, 0x52, 0x54, 0x0e, 0xbd, 0x65, 0xde, 0xbc, 0x7d, 0xf3, 0x66, 0xf4, 0x62, 0xd8, + 0x99, 0x10, 0x21, 0xf0, 0x98, 0x88, 0x77, 0x44, 0x66, 0xa4, 0x20, 0xe5, 0x24, 0x9c, 0x16, 0x5c, + 0x72, 0x7f, 0x37, 0xbb, 0x09, 0x65, 0x41, 0x7e, 0xf2, 0x22, 0x74, 0x94, 0xd0, 0x51, 0x9e, 0x6d, + 0xcf, 0x5f, 0x25, 0x7c, 0x32, 0xe1, 0xcc, 0xbc, 0x09, 0x2e, 0x60, 0xeb, 0xb3, 0xa5, 0x7c, 0x21, + 0xf2, 0xac, 0x1c, 0xe5, 0x34, 0xf9, 0x4a, 0x66, 0xfe, 0x2e, 0x74, 0x70, 0x9a, 0x16, 0x44, 0x88, + 0x98, 0x21, 0xaf, 0xdf, 0x18, 0xf4, 0xa2, 0xb6, 0x05, 0x4e, 0xfd, 0x57, 0xb0, 0x29, 0x32, 0x7e, + 0x13, 0xa7, 0x54, 0x4c, 0x73, 0x3c, 0x43, 0x6b, 0x7d, 0x6f, 0xd0, 0x8e, 0xba, 0x0a, 0x3b, 0x34, + 0x50, 0x30, 0x82, 0xc7, 0x4e, 0x77, 0x21, 0xfa, 0x01, 0x9a, 0x8c, 0xa7, 0x04, 0x79, 0x7d, 0x6f, + 0xd0, 0x7d, 0xff, 0x26, 0xfc, 0x87, 0x5f, 0x6b, 0xee, 0xe8, 0xf0, 0x94, 0xa7, 0x64, 0x38, 0x9b, + 0x92, 0x48, 0x3f, 0xf1, 0x7d, 0x68, 0x56, 0xd3, 0x72, 0xa4, 0x47, 0x75, 0x22, 0xfd, 0x3b, 0x18, + 0x82, 0x5f, 0xf3, 0xbe, 0x6f, 0xdc, 0xdd, 0xdb, 0xf9, 0x77, 0x78, 0xe8, 0x54, 0x9d, 0xe4, 0x4b, + 0x00, 0xab, 0x70, 0x40, 0x99, 0x76, 0xbf, 0x19, 0xd5, 0x90, 0x5a, 0xff, 0x88, 0x54, 0xd6, 0x62, + 0x0d, 0x09, 0xfe, 0xac, 0xc1, 0x03, 0xa7, 0x79, 0x4e, 0xc7, 0x6c, 0x58, 0xdd, 0xed, 0x72, 0x0b, + 0xd6, 0x19, 0x67, 0x09, 0xd1, 0x52, 0x9b, 0x91, 0x29, 0xd4, 0x93, 0x31, 0x16, 0xf1, 0xb4, 0xa0, + 0x09, 0x41, 0x0d, 0xdd, 0x69, 0x8f, 0xb1, 0x38, 0x53, 0xb5, 0x6b, 0xe6, 0x74, 0x42, 0x25, 0x6a, + 0xce, 0x9b, 0x27, 0xaa, 0x56, 0x7a, 0x92, 0x2b, 0xeb, 0xeb, 0x46, 0x4f, 0x17, 0x06, 0x55, 0x86, + 0xbb, 0xda, 0xb0, 0x29, 0x14, 0x7a, 0x8d, 0xf3, 0x92, 0xa0, 0x0d, 0xc3, 0xd5, 0x85, 0xff, 0x16, + 0xfc, 0x14, 0x4b, 0x1c, 0x53, 0x46, 0x25, 0xc5, 0x79, 0x9c, 0x64, 0x25, 0xbb, 0x42, 0x2d, 0x4d, + 0x79, 0xa4, 0x3a, 0xc7, 0xa6, 0xf1, 0x49, 0xe1, 0xfe, 0x1e, 0x74, 0x35, 0x3b, 0x27, 0x6c, 0x2c, + 0x33, 0xd4, 0xee, 0x7b, 0x83, 0x5e, 0x04, 0x0a, 0x3a, 0xd1, 0x88, 0xff, 0x14, 0xda, 0x49, 0x86, + 0x29, 0x8b, 0x69, 0x8a, 0x3a, 0xba, 0xdb, 0xd2, 0xf5, 0x71, 0xea, 0xef, 0x40, 0x4b, 0x56, 0xb1, + 0x9c, 0x4d, 0x09, 0x02, 0xdd, 0xd9, 0x90, 0x95, 0xca, 0x41, 0xf0, 0xdb, 0x5b, 0x44, 0x6a, 0x58, + 0x45, 0xe4, 0x47, 0x49, 0x84, 0x5c, 0x1d, 0xe5, 0xdd, 0x1a, 0xb5, 0x07, 0x5d, 0x41, 0xc7, 0x0c, + 0xcb, 0xb2, 0x20, 0xf1, 0xb5, 0xbe, 0x68, 0x2f, 0x82, 0x39, 0x74, 0xb1, 0x4c, 0x28, 0xec, 0x61, + 0x17, 0x84, 0x68, 0x99, 0x20, 0xec, 0x71, 0x17, 0x84, 0xf3, 0x20, 0x84, 0xde, 0xc2, 0xd8, 0x7e, + 0x72, 0xe5, 0xbf, 0x00, 0xed, 0xc0, 0x5e, 0xc9, 0xe4, 0xa5, 0xa3, 0x10, 0x7d, 0x9e, 0xe0, 0x04, + 0x9e, 0xd4, 0xd3, 0xf0, 0xcd, 0x64, 0xff, 0xee, 0x48, 0x20, 0x68, 0xd9, 0xff, 0x88, 0x0d, 0x85, + 0x2b, 0x83, 0x0a, 0x90, 0x53, 0xb3, 0x4a, 0xe7, 0xce, 0xda, 0x7f, 0x83, 0xfb, 0x1c, 0x3a, 0xf3, + 0x3d, 0xac, 0xee, 0x02, 0x58, 0x89, 0x75, 0xe3, 0x56, 0xac, 0x7f, 0x79, 0xb0, 0xed, 0x46, 0x5f, + 0x90, 0x82, 0x5e, 0xce, 0xdc, 0x2a, 0xf7, 0x9b, 0x5b, 0xdb, 0xb5, 0xb1, 0xb4, 0xeb, 0x8a, 0xa3, + 0xe6, 0xaa, 0xa3, 0x83, 0x8f, 0xf0, 0x3a, 0xe1, 0x93, 0x50, 0x60, 0xc9, 0x45, 0x46, 0x73, 0x3c, + 0x12, 0xee, 0x03, 0x93, 0xd3, 0x91, 0xf9, 0xe2, 0x8d, 0xca, 0xcb, 0x83, 0xed, 0xa1, 0x06, 0xad, + 0x5b, 0xb7, 0xc2, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8a, 0xce, 0x81, 0xc8, 0x59, 0x05, 0x00, + 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.proto new file mode 100644 index 000000000..096bed2e4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-ethereum.proto @@ -0,0 +1,131 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto +// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. + +syntax = "proto2"; +package hw.trezor.messages.ethereum; + +// Sugar for easier handling in Java +option java_package = "com.satoshilabs.trezor.lib.protobuf"; +option java_outer_classname = "TrezorMessageEthereum"; + +import "messages-common.proto"; + + +/** + * Request: Ask device for public key corresponding to address_n path + * @start + * @next EthereumPublicKey + * @next Failure + */ +message EthereumGetPublicKey { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bool show_display = 2; // optionally show on display before sending the result +} + +/** + * Response: Contains public key derived from device private seed + * @end + */ +message EthereumPublicKey { + optional hw.trezor.messages.common.HDNodeType node = 1; // BIP32 public node + optional string xpub = 2; // serialized form of public node +} + +/** + * Request: Ask device for Ethereum address corresponding to address_n path + * @start + * @next EthereumAddress + * @next Failure + */ +message EthereumGetAddress { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bool show_display = 2; // optionally show on display before sending the result +} + +/** + * Response: Contains an Ethereum address derived from device private seed + * @end + */ +message EthereumAddress { + optional bytes addressBin = 1; // Ethereum address as 20 bytes (legacy firmwares) + optional string addressHex = 2; // Ethereum address as hex string (newer firmwares) +} + +/** + * Request: Ask device to sign transaction + * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. + * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. + * @start + * @next EthereumTxRequest + * @next Failure + */ +message EthereumSignTx { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bytes nonce = 2; // <=256 bit unsigned big endian + optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) + optional bytes gas_limit = 4; // <=256 bit unsigned big endian + optional bytes toBin = 5; // recipient address (20 bytes, legacy firmware) + optional string toHex = 11; // recipient address (hex string, newer firmware) + optional bytes value = 6; // <=256 bit unsigned big endian (in wei) + optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) + optional uint32 data_length = 8; // Length of transaction payload + optional uint32 chain_id = 9; // Chain Id for EIP 155 + optional uint32 tx_type = 10; // (only for Wanchain) +} + +/** + * Response: Device asks for more data from transaction payload, or returns the signature. + * If data_length is set, device awaits that many more bytes of payload. + * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. + * @end + * @next EthereumTxAck + */ +message EthereumTxRequest { + optional uint32 data_length = 1; // Number of bytes being requested (<= 1024) + optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28) + optional bytes signature_r = 3; // Computed signature R component (256 bit) + optional bytes signature_s = 4; // Computed signature S component (256 bit) +} + +/** + * Request: Transaction payload data. + * @next EthereumTxRequest + */ +message EthereumTxAck { + optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) +} + +/** + * Request: Ask device to sign message + * @start + * @next EthereumMessageSignature + * @next Failure + */ +message EthereumSignMessage { + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bytes message = 2; // message to be signed +} + +/** + * Response: Signed message + * @end + */ +message EthereumMessageSignature { + optional bytes addressBin = 1; // address used to sign the message (20 bytes, legacy firmware) + optional bytes signature = 2; // signature of the message + optional string addressHex = 3; // address used to sign the message (hex string, newer firmware) +} + +/** + * Request: Ask device to verify message + * @start + * @next Success + * @next Failure + */ +message EthereumVerifyMessage { + optional bytes addressBin = 1; // address to verify (20 bytes, legacy firmware) + optional bytes signature = 2; // signature to verify + optional bytes message = 3; // message to verify + optional string addressHex = 4; // address to verify (hex string, newer firmware) +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.pb.go new file mode 100644 index 000000000..f5c872f1f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.pb.go @@ -0,0 +1,1621 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages-management.proto + +package trezor + +import ( + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +//* +// Structure representing passphrase source +type ApplySettings_PassphraseSourceType int32 + +const ( + ApplySettings_ASK ApplySettings_PassphraseSourceType = 0 + ApplySettings_DEVICE ApplySettings_PassphraseSourceType = 1 + ApplySettings_HOST ApplySettings_PassphraseSourceType = 2 +) + +var ApplySettings_PassphraseSourceType_name = map[int32]string{ + 0: "ASK", + 1: "DEVICE", + 2: "HOST", +} + +var ApplySettings_PassphraseSourceType_value = map[string]int32{ + "ASK": 0, + "DEVICE": 1, + "HOST": 2, +} + +func (x ApplySettings_PassphraseSourceType) Enum() *ApplySettings_PassphraseSourceType { + p := new(ApplySettings_PassphraseSourceType) + *p = x + return p +} + +func (x ApplySettings_PassphraseSourceType) String() string { + return proto.EnumName(ApplySettings_PassphraseSourceType_name, int32(x)) +} + +func (x *ApplySettings_PassphraseSourceType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(ApplySettings_PassphraseSourceType_value, data, "ApplySettings_PassphraseSourceType") + if err != nil { + return err + } + *x = ApplySettings_PassphraseSourceType(value) + return nil +} + +func (ApplySettings_PassphraseSourceType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{4, 0} +} + +//* +// Type of recovery procedure. These should be used as bitmask, e.g., +// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` +// listing every method supported by the host computer. +// +// Note that ScrambledWords must be supported by every implementation +// for backward compatibility; there is no way to not support it. +type RecoveryDevice_RecoveryDeviceType int32 + +const ( + // use powers of two when extending this field + RecoveryDevice_RecoveryDeviceType_ScrambledWords RecoveryDevice_RecoveryDeviceType = 0 + RecoveryDevice_RecoveryDeviceType_Matrix RecoveryDevice_RecoveryDeviceType = 1 +) + +var RecoveryDevice_RecoveryDeviceType_name = map[int32]string{ + 0: "RecoveryDeviceType_ScrambledWords", + 1: "RecoveryDeviceType_Matrix", +} + +var RecoveryDevice_RecoveryDeviceType_value = map[string]int32{ + "RecoveryDeviceType_ScrambledWords": 0, + "RecoveryDeviceType_Matrix": 1, +} + +func (x RecoveryDevice_RecoveryDeviceType) Enum() *RecoveryDevice_RecoveryDeviceType { + p := new(RecoveryDevice_RecoveryDeviceType) + *p = x + return p +} + +func (x RecoveryDevice_RecoveryDeviceType) String() string { + return proto.EnumName(RecoveryDevice_RecoveryDeviceType_name, int32(x)) +} + +func (x *RecoveryDevice_RecoveryDeviceType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RecoveryDevice_RecoveryDeviceType_value, data, "RecoveryDevice_RecoveryDeviceType") + if err != nil { + return err + } + *x = RecoveryDevice_RecoveryDeviceType(value) + return nil +} + +func (RecoveryDevice_RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{17, 0} +} + +//* +// Type of Recovery Word request +type WordRequest_WordRequestType int32 + +const ( + WordRequest_WordRequestType_Plain WordRequest_WordRequestType = 0 + WordRequest_WordRequestType_Matrix9 WordRequest_WordRequestType = 1 + WordRequest_WordRequestType_Matrix6 WordRequest_WordRequestType = 2 +) + +var WordRequest_WordRequestType_name = map[int32]string{ + 0: "WordRequestType_Plain", + 1: "WordRequestType_Matrix9", + 2: "WordRequestType_Matrix6", +} + +var WordRequest_WordRequestType_value = map[string]int32{ + "WordRequestType_Plain": 0, + "WordRequestType_Matrix9": 1, + "WordRequestType_Matrix6": 2, +} + +func (x WordRequest_WordRequestType) Enum() *WordRequest_WordRequestType { + p := new(WordRequest_WordRequestType) + *p = x + return p +} + +func (x WordRequest_WordRequestType) String() string { + return proto.EnumName(WordRequest_WordRequestType_name, int32(x)) +} + +func (x *WordRequest_WordRequestType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(WordRequest_WordRequestType_value, data, "WordRequest_WordRequestType") + if err != nil { + return err + } + *x = WordRequest_WordRequestType(value) + return nil +} + +func (WordRequest_WordRequestType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{18, 0} +} + +//* +// Request: Reset device to default state and ask for device details +// @start +// @next Features +type Initialize struct { + State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` + SkipPassphrase *bool `protobuf:"varint,2,opt,name=skip_passphrase,json=skipPassphrase" json:"skip_passphrase,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Initialize) Reset() { *m = Initialize{} } +func (m *Initialize) String() string { return proto.CompactTextString(m) } +func (*Initialize) ProtoMessage() {} +func (*Initialize) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{0} +} + +func (m *Initialize) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Initialize.Unmarshal(m, b) +} +func (m *Initialize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Initialize.Marshal(b, m, deterministic) +} +func (m *Initialize) XXX_Merge(src proto.Message) { + xxx_messageInfo_Initialize.Merge(m, src) +} +func (m *Initialize) XXX_Size() int { + return xxx_messageInfo_Initialize.Size(m) +} +func (m *Initialize) XXX_DiscardUnknown() { + xxx_messageInfo_Initialize.DiscardUnknown(m) +} + +var xxx_messageInfo_Initialize proto.InternalMessageInfo + +func (m *Initialize) GetState() []byte { + if m != nil { + return m.State + } + return nil +} + +func (m *Initialize) GetSkipPassphrase() bool { + if m != nil && m.SkipPassphrase != nil { + return *m.SkipPassphrase + } + return false +} + +//* +// Request: Ask for device details (no device reset) +// @start +// @next Features +type GetFeatures struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetFeatures) Reset() { *m = GetFeatures{} } +func (m *GetFeatures) String() string { return proto.CompactTextString(m) } +func (*GetFeatures) ProtoMessage() {} +func (*GetFeatures) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{1} +} + +func (m *GetFeatures) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetFeatures.Unmarshal(m, b) +} +func (m *GetFeatures) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetFeatures.Marshal(b, m, deterministic) +} +func (m *GetFeatures) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetFeatures.Merge(m, src) +} +func (m *GetFeatures) XXX_Size() int { + return xxx_messageInfo_GetFeatures.Size(m) +} +func (m *GetFeatures) XXX_DiscardUnknown() { + xxx_messageInfo_GetFeatures.DiscardUnknown(m) +} + +var xxx_messageInfo_GetFeatures proto.InternalMessageInfo + +//* +// Response: Reports various information about the device +// @end +type Features struct { + Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` + MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` + MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` + PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` + BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` + DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` + PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` + Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` + Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` + Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` + BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` + Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` + PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` + PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` + FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` + NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` + Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` + Model *string `protobuf:"bytes,21,opt,name=model" json:"model,omitempty"` + FwMajor *uint32 `protobuf:"varint,22,opt,name=fw_major,json=fwMajor" json:"fw_major,omitempty"` + FwMinor *uint32 `protobuf:"varint,23,opt,name=fw_minor,json=fwMinor" json:"fw_minor,omitempty"` + FwPatch *uint32 `protobuf:"varint,24,opt,name=fw_patch,json=fwPatch" json:"fw_patch,omitempty"` + FwVendor *string `protobuf:"bytes,25,opt,name=fw_vendor,json=fwVendor" json:"fw_vendor,omitempty"` + FwVendorKeys []byte `protobuf:"bytes,26,opt,name=fw_vendor_keys,json=fwVendorKeys" json:"fw_vendor_keys,omitempty"` + UnfinishedBackup *bool `protobuf:"varint,27,opt,name=unfinished_backup,json=unfinishedBackup" json:"unfinished_backup,omitempty"` + NoBackup *bool `protobuf:"varint,28,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Features) Reset() { *m = Features{} } +func (m *Features) String() string { return proto.CompactTextString(m) } +func (*Features) ProtoMessage() {} +func (*Features) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{2} +} + +func (m *Features) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Features.Unmarshal(m, b) +} +func (m *Features) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Features.Marshal(b, m, deterministic) +} +func (m *Features) XXX_Merge(src proto.Message) { + xxx_messageInfo_Features.Merge(m, src) +} +func (m *Features) XXX_Size() int { + return xxx_messageInfo_Features.Size(m) +} +func (m *Features) XXX_DiscardUnknown() { + xxx_messageInfo_Features.DiscardUnknown(m) +} + +var xxx_messageInfo_Features proto.InternalMessageInfo + +func (m *Features) GetVendor() string { + if m != nil && m.Vendor != nil { + return *m.Vendor + } + return "" +} + +func (m *Features) GetMajorVersion() uint32 { + if m != nil && m.MajorVersion != nil { + return *m.MajorVersion + } + return 0 +} + +func (m *Features) GetMinorVersion() uint32 { + if m != nil && m.MinorVersion != nil { + return *m.MinorVersion + } + return 0 +} + +func (m *Features) GetPatchVersion() uint32 { + if m != nil && m.PatchVersion != nil { + return *m.PatchVersion + } + return 0 +} + +func (m *Features) GetBootloaderMode() bool { + if m != nil && m.BootloaderMode != nil { + return *m.BootloaderMode + } + return false +} + +func (m *Features) GetDeviceId() string { + if m != nil && m.DeviceId != nil { + return *m.DeviceId + } + return "" +} + +func (m *Features) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *Features) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *Features) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return "" +} + +func (m *Features) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *Features) GetInitialized() bool { + if m != nil && m.Initialized != nil { + return *m.Initialized + } + return false +} + +func (m *Features) GetRevision() []byte { + if m != nil { + return m.Revision + } + return nil +} + +func (m *Features) GetBootloaderHash() []byte { + if m != nil { + return m.BootloaderHash + } + return nil +} + +func (m *Features) GetImported() bool { + if m != nil && m.Imported != nil { + return *m.Imported + } + return false +} + +func (m *Features) GetPinCached() bool { + if m != nil && m.PinCached != nil { + return *m.PinCached + } + return false +} + +func (m *Features) GetPassphraseCached() bool { + if m != nil && m.PassphraseCached != nil { + return *m.PassphraseCached + } + return false +} + +func (m *Features) GetFirmwarePresent() bool { + if m != nil && m.FirmwarePresent != nil { + return *m.FirmwarePresent + } + return false +} + +func (m *Features) GetNeedsBackup() bool { + if m != nil && m.NeedsBackup != nil { + return *m.NeedsBackup + } + return false +} + +func (m *Features) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +func (m *Features) GetModel() string { + if m != nil && m.Model != nil { + return *m.Model + } + return "" +} + +func (m *Features) GetFwMajor() uint32 { + if m != nil && m.FwMajor != nil { + return *m.FwMajor + } + return 0 +} + +func (m *Features) GetFwMinor() uint32 { + if m != nil && m.FwMinor != nil { + return *m.FwMinor + } + return 0 +} + +func (m *Features) GetFwPatch() uint32 { + if m != nil && m.FwPatch != nil { + return *m.FwPatch + } + return 0 +} + +func (m *Features) GetFwVendor() string { + if m != nil && m.FwVendor != nil { + return *m.FwVendor + } + return "" +} + +func (m *Features) GetFwVendorKeys() []byte { + if m != nil { + return m.FwVendorKeys + } + return nil +} + +func (m *Features) GetUnfinishedBackup() bool { + if m != nil && m.UnfinishedBackup != nil { + return *m.UnfinishedBackup + } + return false +} + +func (m *Features) GetNoBackup() bool { + if m != nil && m.NoBackup != nil { + return *m.NoBackup + } + return false +} + +//* +// Request: clear session (removes cached PIN, passphrase, etc). +// @start +// @next Success +type ClearSession struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ClearSession) Reset() { *m = ClearSession{} } +func (m *ClearSession) String() string { return proto.CompactTextString(m) } +func (*ClearSession) ProtoMessage() {} +func (*ClearSession) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{3} +} + +func (m *ClearSession) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ClearSession.Unmarshal(m, b) +} +func (m *ClearSession) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ClearSession.Marshal(b, m, deterministic) +} +func (m *ClearSession) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClearSession.Merge(m, src) +} +func (m *ClearSession) XXX_Size() int { + return xxx_messageInfo_ClearSession.Size(m) +} +func (m *ClearSession) XXX_DiscardUnknown() { + xxx_messageInfo_ClearSession.DiscardUnknown(m) +} + +var xxx_messageInfo_ClearSession proto.InternalMessageInfo + +//* +// Request: change language and/or label of the device +// @start +// @next Success +// @next Failure +type ApplySettings struct { + Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"` + Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"` + UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"` + Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"` + PassphraseSource *ApplySettings_PassphraseSourceType `protobuf:"varint,5,opt,name=passphrase_source,json=passphraseSource,enum=hw.trezor.messages.management.ApplySettings_PassphraseSourceType" json:"passphrase_source,omitempty"` + AutoLockDelayMs *uint32 `protobuf:"varint,6,opt,name=auto_lock_delay_ms,json=autoLockDelayMs" json:"auto_lock_delay_ms,omitempty"` + DisplayRotation *uint32 `protobuf:"varint,7,opt,name=display_rotation,json=displayRotation" json:"display_rotation,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApplySettings) Reset() { *m = ApplySettings{} } +func (m *ApplySettings) String() string { return proto.CompactTextString(m) } +func (*ApplySettings) ProtoMessage() {} +func (*ApplySettings) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{4} +} + +func (m *ApplySettings) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApplySettings.Unmarshal(m, b) +} +func (m *ApplySettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApplySettings.Marshal(b, m, deterministic) +} +func (m *ApplySettings) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApplySettings.Merge(m, src) +} +func (m *ApplySettings) XXX_Size() int { + return xxx_messageInfo_ApplySettings.Size(m) +} +func (m *ApplySettings) XXX_DiscardUnknown() { + xxx_messageInfo_ApplySettings.DiscardUnknown(m) +} + +var xxx_messageInfo_ApplySettings proto.InternalMessageInfo + +func (m *ApplySettings) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return "" +} + +func (m *ApplySettings) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *ApplySettings) GetUsePassphrase() bool { + if m != nil && m.UsePassphrase != nil { + return *m.UsePassphrase + } + return false +} + +func (m *ApplySettings) GetHomescreen() []byte { + if m != nil { + return m.Homescreen + } + return nil +} + +func (m *ApplySettings) GetPassphraseSource() ApplySettings_PassphraseSourceType { + if m != nil && m.PassphraseSource != nil { + return *m.PassphraseSource + } + return ApplySettings_ASK +} + +func (m *ApplySettings) GetAutoLockDelayMs() uint32 { + if m != nil && m.AutoLockDelayMs != nil { + return *m.AutoLockDelayMs + } + return 0 +} + +func (m *ApplySettings) GetDisplayRotation() uint32 { + if m != nil && m.DisplayRotation != nil { + return *m.DisplayRotation + } + return 0 +} + +//* +// Request: set flags of the device +// @start +// @next Success +// @next Failure +type ApplyFlags struct { + Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ApplyFlags) Reset() { *m = ApplyFlags{} } +func (m *ApplyFlags) String() string { return proto.CompactTextString(m) } +func (*ApplyFlags) ProtoMessage() {} +func (*ApplyFlags) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{5} +} + +func (m *ApplyFlags) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ApplyFlags.Unmarshal(m, b) +} +func (m *ApplyFlags) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ApplyFlags.Marshal(b, m, deterministic) +} +func (m *ApplyFlags) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApplyFlags.Merge(m, src) +} +func (m *ApplyFlags) XXX_Size() int { + return xxx_messageInfo_ApplyFlags.Size(m) +} +func (m *ApplyFlags) XXX_DiscardUnknown() { + xxx_messageInfo_ApplyFlags.DiscardUnknown(m) +} + +var xxx_messageInfo_ApplyFlags proto.InternalMessageInfo + +func (m *ApplyFlags) GetFlags() uint32 { + if m != nil && m.Flags != nil { + return *m.Flags + } + return 0 +} + +//* +// Request: Starts workflow for setting/changing/removing the PIN +// @start +// @next Success +// @next Failure +type ChangePin struct { + Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ChangePin) Reset() { *m = ChangePin{} } +func (m *ChangePin) String() string { return proto.CompactTextString(m) } +func (*ChangePin) ProtoMessage() {} +func (*ChangePin) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{6} +} + +func (m *ChangePin) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChangePin.Unmarshal(m, b) +} +func (m *ChangePin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChangePin.Marshal(b, m, deterministic) +} +func (m *ChangePin) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChangePin.Merge(m, src) +} +func (m *ChangePin) XXX_Size() int { + return xxx_messageInfo_ChangePin.Size(m) +} +func (m *ChangePin) XXX_DiscardUnknown() { + xxx_messageInfo_ChangePin.DiscardUnknown(m) +} + +var xxx_messageInfo_ChangePin proto.InternalMessageInfo + +func (m *ChangePin) GetRemove() bool { + if m != nil && m.Remove != nil { + return *m.Remove + } + return false +} + +//* +// Request: Test if the device is alive, device sends back the message in Success response +// @start +// @next Success +type Ping struct { + Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` + PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Ping) Reset() { *m = Ping{} } +func (m *Ping) String() string { return proto.CompactTextString(m) } +func (*Ping) ProtoMessage() {} +func (*Ping) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{7} +} + +func (m *Ping) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Ping.Unmarshal(m, b) +} +func (m *Ping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Ping.Marshal(b, m, deterministic) +} +func (m *Ping) XXX_Merge(src proto.Message) { + xxx_messageInfo_Ping.Merge(m, src) +} +func (m *Ping) XXX_Size() int { + return xxx_messageInfo_Ping.Size(m) +} +func (m *Ping) XXX_DiscardUnknown() { + xxx_messageInfo_Ping.DiscardUnknown(m) +} + +var xxx_messageInfo_Ping proto.InternalMessageInfo + +func (m *Ping) GetMessage() string { + if m != nil && m.Message != nil { + return *m.Message + } + return "" +} + +func (m *Ping) GetButtonProtection() bool { + if m != nil && m.ButtonProtection != nil { + return *m.ButtonProtection + } + return false +} + +func (m *Ping) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *Ping) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +//* +// Request: Abort last operation that required user interaction +// @start +// @next Failure +type Cancel struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Cancel) Reset() { *m = Cancel{} } +func (m *Cancel) String() string { return proto.CompactTextString(m) } +func (*Cancel) ProtoMessage() {} +func (*Cancel) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{8} +} + +func (m *Cancel) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Cancel.Unmarshal(m, b) +} +func (m *Cancel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Cancel.Marshal(b, m, deterministic) +} +func (m *Cancel) XXX_Merge(src proto.Message) { + xxx_messageInfo_Cancel.Merge(m, src) +} +func (m *Cancel) XXX_Size() int { + return xxx_messageInfo_Cancel.Size(m) +} +func (m *Cancel) XXX_DiscardUnknown() { + xxx_messageInfo_Cancel.DiscardUnknown(m) +} + +var xxx_messageInfo_Cancel proto.InternalMessageInfo + +//* +// Request: Request a sample of random data generated by hardware RNG. May be used for testing. +// @start +// @next Entropy +// @next Failure +type GetEntropy struct { + Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetEntropy) Reset() { *m = GetEntropy{} } +func (m *GetEntropy) String() string { return proto.CompactTextString(m) } +func (*GetEntropy) ProtoMessage() {} +func (*GetEntropy) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{9} +} + +func (m *GetEntropy) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetEntropy.Unmarshal(m, b) +} +func (m *GetEntropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetEntropy.Marshal(b, m, deterministic) +} +func (m *GetEntropy) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetEntropy.Merge(m, src) +} +func (m *GetEntropy) XXX_Size() int { + return xxx_messageInfo_GetEntropy.Size(m) +} +func (m *GetEntropy) XXX_DiscardUnknown() { + xxx_messageInfo_GetEntropy.DiscardUnknown(m) +} + +var xxx_messageInfo_GetEntropy proto.InternalMessageInfo + +func (m *GetEntropy) GetSize() uint32 { + if m != nil && m.Size != nil { + return *m.Size + } + return 0 +} + +//* +// Response: Reply with random data generated by internal RNG +// @end +type Entropy struct { + Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Entropy) Reset() { *m = Entropy{} } +func (m *Entropy) String() string { return proto.CompactTextString(m) } +func (*Entropy) ProtoMessage() {} +func (*Entropy) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{10} +} + +func (m *Entropy) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Entropy.Unmarshal(m, b) +} +func (m *Entropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Entropy.Marshal(b, m, deterministic) +} +func (m *Entropy) XXX_Merge(src proto.Message) { + xxx_messageInfo_Entropy.Merge(m, src) +} +func (m *Entropy) XXX_Size() int { + return xxx_messageInfo_Entropy.Size(m) +} +func (m *Entropy) XXX_DiscardUnknown() { + xxx_messageInfo_Entropy.DiscardUnknown(m) +} + +var xxx_messageInfo_Entropy proto.InternalMessageInfo + +func (m *Entropy) GetEntropy() []byte { + if m != nil { + return m.Entropy + } + return nil +} + +//* +// Request: Request device to wipe all sensitive data and settings +// @start +// @next Success +// @next Failure +type WipeDevice struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WipeDevice) Reset() { *m = WipeDevice{} } +func (m *WipeDevice) String() string { return proto.CompactTextString(m) } +func (*WipeDevice) ProtoMessage() {} +func (*WipeDevice) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{11} +} + +func (m *WipeDevice) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_WipeDevice.Unmarshal(m, b) +} +func (m *WipeDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_WipeDevice.Marshal(b, m, deterministic) +} +func (m *WipeDevice) XXX_Merge(src proto.Message) { + xxx_messageInfo_WipeDevice.Merge(m, src) +} +func (m *WipeDevice) XXX_Size() int { + return xxx_messageInfo_WipeDevice.Size(m) +} +func (m *WipeDevice) XXX_DiscardUnknown() { + xxx_messageInfo_WipeDevice.DiscardUnknown(m) +} + +var xxx_messageInfo_WipeDevice proto.InternalMessageInfo + +//* +// Request: Load seed and related internal settings from the computer +// @start +// @next Success +// @next Failure +type LoadDevice struct { + Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` + Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` + Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` + PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` + SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` + U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LoadDevice) Reset() { *m = LoadDevice{} } +func (m *LoadDevice) String() string { return proto.CompactTextString(m) } +func (*LoadDevice) ProtoMessage() {} +func (*LoadDevice) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{12} +} + +func (m *LoadDevice) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LoadDevice.Unmarshal(m, b) +} +func (m *LoadDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LoadDevice.Marshal(b, m, deterministic) +} +func (m *LoadDevice) XXX_Merge(src proto.Message) { + xxx_messageInfo_LoadDevice.Merge(m, src) +} +func (m *LoadDevice) XXX_Size() int { + return xxx_messageInfo_LoadDevice.Size(m) +} +func (m *LoadDevice) XXX_DiscardUnknown() { + xxx_messageInfo_LoadDevice.DiscardUnknown(m) +} + +var xxx_messageInfo_LoadDevice proto.InternalMessageInfo + +const Default_LoadDevice_Language string = "english" + +func (m *LoadDevice) GetMnemonic() string { + if m != nil && m.Mnemonic != nil { + return *m.Mnemonic + } + return "" +} + +func (m *LoadDevice) GetNode() *HDNodeType { + if m != nil { + return m.Node + } + return nil +} + +func (m *LoadDevice) GetPin() string { + if m != nil && m.Pin != nil { + return *m.Pin + } + return "" +} + +func (m *LoadDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *LoadDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_LoadDevice_Language +} + +func (m *LoadDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *LoadDevice) GetSkipChecksum() bool { + if m != nil && m.SkipChecksum != nil { + return *m.SkipChecksum + } + return false +} + +func (m *LoadDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +//* +// Request: Ask device to do initialization involving user interaction +// @start +// @next EntropyRequest +// @next Failure +type ResetDevice struct { + DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` + Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` + PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` + U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` + NoBackup *bool `protobuf:"varint,9,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ResetDevice) Reset() { *m = ResetDevice{} } +func (m *ResetDevice) String() string { return proto.CompactTextString(m) } +func (*ResetDevice) ProtoMessage() {} +func (*ResetDevice) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{13} +} + +func (m *ResetDevice) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ResetDevice.Unmarshal(m, b) +} +func (m *ResetDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ResetDevice.Marshal(b, m, deterministic) +} +func (m *ResetDevice) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResetDevice.Merge(m, src) +} +func (m *ResetDevice) XXX_Size() int { + return xxx_messageInfo_ResetDevice.Size(m) +} +func (m *ResetDevice) XXX_DiscardUnknown() { + xxx_messageInfo_ResetDevice.DiscardUnknown(m) +} + +var xxx_messageInfo_ResetDevice proto.InternalMessageInfo + +const Default_ResetDevice_Strength uint32 = 256 +const Default_ResetDevice_Language string = "english" + +func (m *ResetDevice) GetDisplayRandom() bool { + if m != nil && m.DisplayRandom != nil { + return *m.DisplayRandom + } + return false +} + +func (m *ResetDevice) GetStrength() uint32 { + if m != nil && m.Strength != nil { + return *m.Strength + } + return Default_ResetDevice_Strength +} + +func (m *ResetDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *ResetDevice) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *ResetDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_ResetDevice_Language +} + +func (m *ResetDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *ResetDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +func (m *ResetDevice) GetSkipBackup() bool { + if m != nil && m.SkipBackup != nil { + return *m.SkipBackup + } + return false +} + +func (m *ResetDevice) GetNoBackup() bool { + if m != nil && m.NoBackup != nil { + return *m.NoBackup + } + return false +} + +//* +// Request: Perform backup of the device seed if not backed up using ResetDevice +// @start +// @next Success +type BackupDevice struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BackupDevice) Reset() { *m = BackupDevice{} } +func (m *BackupDevice) String() string { return proto.CompactTextString(m) } +func (*BackupDevice) ProtoMessage() {} +func (*BackupDevice) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{14} +} + +func (m *BackupDevice) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BackupDevice.Unmarshal(m, b) +} +func (m *BackupDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BackupDevice.Marshal(b, m, deterministic) +} +func (m *BackupDevice) XXX_Merge(src proto.Message) { + xxx_messageInfo_BackupDevice.Merge(m, src) +} +func (m *BackupDevice) XXX_Size() int { + return xxx_messageInfo_BackupDevice.Size(m) +} +func (m *BackupDevice) XXX_DiscardUnknown() { + xxx_messageInfo_BackupDevice.DiscardUnknown(m) +} + +var xxx_messageInfo_BackupDevice proto.InternalMessageInfo + +//* +// Response: Ask for additional entropy from host computer +// @next EntropyAck +type EntropyRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EntropyRequest) Reset() { *m = EntropyRequest{} } +func (m *EntropyRequest) String() string { return proto.CompactTextString(m) } +func (*EntropyRequest) ProtoMessage() {} +func (*EntropyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{15} +} + +func (m *EntropyRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EntropyRequest.Unmarshal(m, b) +} +func (m *EntropyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EntropyRequest.Marshal(b, m, deterministic) +} +func (m *EntropyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EntropyRequest.Merge(m, src) +} +func (m *EntropyRequest) XXX_Size() int { + return xxx_messageInfo_EntropyRequest.Size(m) +} +func (m *EntropyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EntropyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EntropyRequest proto.InternalMessageInfo + +//* +// Request: Provide additional entropy for seed generation function +// @next Success +type EntropyAck struct { + Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EntropyAck) Reset() { *m = EntropyAck{} } +func (m *EntropyAck) String() string { return proto.CompactTextString(m) } +func (*EntropyAck) ProtoMessage() {} +func (*EntropyAck) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{16} +} + +func (m *EntropyAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EntropyAck.Unmarshal(m, b) +} +func (m *EntropyAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EntropyAck.Marshal(b, m, deterministic) +} +func (m *EntropyAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_EntropyAck.Merge(m, src) +} +func (m *EntropyAck) XXX_Size() int { + return xxx_messageInfo_EntropyAck.Size(m) +} +func (m *EntropyAck) XXX_DiscardUnknown() { + xxx_messageInfo_EntropyAck.DiscardUnknown(m) +} + +var xxx_messageInfo_EntropyAck proto.InternalMessageInfo + +func (m *EntropyAck) GetEntropy() []byte { + if m != nil { + return m.Entropy + } + return nil +} + +//* +// Request: Start recovery workflow asking user for specific words of mnemonic +// Used to recovery device safely even on untrusted computer. +// @start +// @next WordRequest +type RecoveryDevice struct { + WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` + PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` + PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` + Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` + Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` + EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` + // 7 reserved for unused recovery method + Type *RecoveryDevice_RecoveryDeviceType `protobuf:"varint,8,opt,name=type,enum=hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType" json:"type,omitempty"` + U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RecoveryDevice) Reset() { *m = RecoveryDevice{} } +func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) } +func (*RecoveryDevice) ProtoMessage() {} +func (*RecoveryDevice) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{17} +} + +func (m *RecoveryDevice) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RecoveryDevice.Unmarshal(m, b) +} +func (m *RecoveryDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RecoveryDevice.Marshal(b, m, deterministic) +} +func (m *RecoveryDevice) XXX_Merge(src proto.Message) { + xxx_messageInfo_RecoveryDevice.Merge(m, src) +} +func (m *RecoveryDevice) XXX_Size() int { + return xxx_messageInfo_RecoveryDevice.Size(m) +} +func (m *RecoveryDevice) XXX_DiscardUnknown() { + xxx_messageInfo_RecoveryDevice.DiscardUnknown(m) +} + +var xxx_messageInfo_RecoveryDevice proto.InternalMessageInfo + +const Default_RecoveryDevice_Language string = "english" + +func (m *RecoveryDevice) GetWordCount() uint32 { + if m != nil && m.WordCount != nil { + return *m.WordCount + } + return 0 +} + +func (m *RecoveryDevice) GetPassphraseProtection() bool { + if m != nil && m.PassphraseProtection != nil { + return *m.PassphraseProtection + } + return false +} + +func (m *RecoveryDevice) GetPinProtection() bool { + if m != nil && m.PinProtection != nil { + return *m.PinProtection + } + return false +} + +func (m *RecoveryDevice) GetLanguage() string { + if m != nil && m.Language != nil { + return *m.Language + } + return Default_RecoveryDevice_Language +} + +func (m *RecoveryDevice) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *RecoveryDevice) GetEnforceWordlist() bool { + if m != nil && m.EnforceWordlist != nil { + return *m.EnforceWordlist + } + return false +} + +func (m *RecoveryDevice) GetType() RecoveryDevice_RecoveryDeviceType { + if m != nil && m.Type != nil { + return *m.Type + } + return RecoveryDevice_RecoveryDeviceType_ScrambledWords +} + +func (m *RecoveryDevice) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +func (m *RecoveryDevice) GetDryRun() bool { + if m != nil && m.DryRun != nil { + return *m.DryRun + } + return false +} + +//* +// Response: Device is waiting for user to enter word of the mnemonic +// Its position is shown only on device's internal display. +// @next WordAck +type WordRequest struct { + Type *WordRequest_WordRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.management.WordRequest_WordRequestType" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WordRequest) Reset() { *m = WordRequest{} } +func (m *WordRequest) String() string { return proto.CompactTextString(m) } +func (*WordRequest) ProtoMessage() {} +func (*WordRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{18} +} + +func (m *WordRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_WordRequest.Unmarshal(m, b) +} +func (m *WordRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_WordRequest.Marshal(b, m, deterministic) +} +func (m *WordRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_WordRequest.Merge(m, src) +} +func (m *WordRequest) XXX_Size() int { + return xxx_messageInfo_WordRequest.Size(m) +} +func (m *WordRequest) XXX_DiscardUnknown() { + xxx_messageInfo_WordRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_WordRequest proto.InternalMessageInfo + +func (m *WordRequest) GetType() WordRequest_WordRequestType { + if m != nil && m.Type != nil { + return *m.Type + } + return WordRequest_WordRequestType_Plain +} + +//* +// Request: Computer replies with word from the mnemonic +// @next WordRequest +// @next Success +// @next Failure +type WordAck struct { + Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *WordAck) Reset() { *m = WordAck{} } +func (m *WordAck) String() string { return proto.CompactTextString(m) } +func (*WordAck) ProtoMessage() {} +func (*WordAck) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{19} +} + +func (m *WordAck) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_WordAck.Unmarshal(m, b) +} +func (m *WordAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_WordAck.Marshal(b, m, deterministic) +} +func (m *WordAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_WordAck.Merge(m, src) +} +func (m *WordAck) XXX_Size() int { + return xxx_messageInfo_WordAck.Size(m) +} +func (m *WordAck) XXX_DiscardUnknown() { + xxx_messageInfo_WordAck.DiscardUnknown(m) +} + +var xxx_messageInfo_WordAck proto.InternalMessageInfo + +func (m *WordAck) GetWord() string { + if m != nil && m.Word != nil { + return *m.Word + } + return "" +} + +//* +// Request: Set U2F counter +// @start +// @next Success +type SetU2FCounter struct { + U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SetU2FCounter) Reset() { *m = SetU2FCounter{} } +func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) } +func (*SetU2FCounter) ProtoMessage() {} +func (*SetU2FCounter) Descriptor() ([]byte, []int) { + return fileDescriptor_0c720c20d27aa029, []int{20} +} + +func (m *SetU2FCounter) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SetU2FCounter.Unmarshal(m, b) +} +func (m *SetU2FCounter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SetU2FCounter.Marshal(b, m, deterministic) +} +func (m *SetU2FCounter) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetU2FCounter.Merge(m, src) +} +func (m *SetU2FCounter) XXX_Size() int { + return xxx_messageInfo_SetU2FCounter.Size(m) +} +func (m *SetU2FCounter) XXX_DiscardUnknown() { + xxx_messageInfo_SetU2FCounter.DiscardUnknown(m) +} + +var xxx_messageInfo_SetU2FCounter proto.InternalMessageInfo + +func (m *SetU2FCounter) GetU2FCounter() uint32 { + if m != nil && m.U2FCounter != nil { + return *m.U2FCounter + } + return 0 +} + +func init() { + proto.RegisterEnum("hw.trezor.messages.management.ApplySettings_PassphraseSourceType", ApplySettings_PassphraseSourceType_name, ApplySettings_PassphraseSourceType_value) + proto.RegisterEnum("hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType", RecoveryDevice_RecoveryDeviceType_name, RecoveryDevice_RecoveryDeviceType_value) + proto.RegisterEnum("hw.trezor.messages.management.WordRequest_WordRequestType", WordRequest_WordRequestType_name, WordRequest_WordRequestType_value) + proto.RegisterType((*Initialize)(nil), "hw.trezor.messages.management.Initialize") + proto.RegisterType((*GetFeatures)(nil), "hw.trezor.messages.management.GetFeatures") + proto.RegisterType((*Features)(nil), "hw.trezor.messages.management.Features") + proto.RegisterType((*ClearSession)(nil), "hw.trezor.messages.management.ClearSession") + proto.RegisterType((*ApplySettings)(nil), "hw.trezor.messages.management.ApplySettings") + proto.RegisterType((*ApplyFlags)(nil), "hw.trezor.messages.management.ApplyFlags") + proto.RegisterType((*ChangePin)(nil), "hw.trezor.messages.management.ChangePin") + proto.RegisterType((*Ping)(nil), "hw.trezor.messages.management.Ping") + proto.RegisterType((*Cancel)(nil), "hw.trezor.messages.management.Cancel") + proto.RegisterType((*GetEntropy)(nil), "hw.trezor.messages.management.GetEntropy") + proto.RegisterType((*Entropy)(nil), "hw.trezor.messages.management.Entropy") + proto.RegisterType((*WipeDevice)(nil), "hw.trezor.messages.management.WipeDevice") + proto.RegisterType((*LoadDevice)(nil), "hw.trezor.messages.management.LoadDevice") + proto.RegisterType((*ResetDevice)(nil), "hw.trezor.messages.management.ResetDevice") + proto.RegisterType((*BackupDevice)(nil), "hw.trezor.messages.management.BackupDevice") + proto.RegisterType((*EntropyRequest)(nil), "hw.trezor.messages.management.EntropyRequest") + proto.RegisterType((*EntropyAck)(nil), "hw.trezor.messages.management.EntropyAck") + proto.RegisterType((*RecoveryDevice)(nil), "hw.trezor.messages.management.RecoveryDevice") + proto.RegisterType((*WordRequest)(nil), "hw.trezor.messages.management.WordRequest") + proto.RegisterType((*WordAck)(nil), "hw.trezor.messages.management.WordAck") + proto.RegisterType((*SetU2FCounter)(nil), "hw.trezor.messages.management.SetU2FCounter") +} + +func init() { proto.RegisterFile("messages-management.proto", fileDescriptor_0c720c20d27aa029) } + +var fileDescriptor_0c720c20d27aa029 = []byte{ + // 1393 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xdd, 0x6e, 0xdb, 0xc8, + 0x15, 0x8e, 0x7e, 0x62, 0x49, 0xc7, 0xfa, 0xcb, 0xd4, 0x8e, 0xe9, 0xb8, 0x6e, 0x1c, 0xba, 0x6e, + 0x12, 0x04, 0x15, 0x0a, 0x17, 0x09, 0x90, 0x5c, 0x14, 0x75, 0xec, 0xfc, 0x21, 0x71, 0x6a, 0xd0, + 0x6e, 0x02, 0xf4, 0x86, 0x18, 0x91, 0x47, 0xd2, 0xd4, 0xe4, 0x0c, 0xcb, 0x19, 0xda, 0x55, 0x5e, + 0x60, 0x6f, 0xf6, 0x45, 0x16, 0xfb, 0x1c, 0x7b, 0xb5, 0xcf, 0xb0, 0xef, 0xb2, 0x98, 0x19, 0x52, + 0xa2, 0x65, 0x3b, 0x46, 0x76, 0xef, 0xe6, 0x7c, 0xe7, 0xe3, 0x68, 0xce, 0x77, 0xbe, 0x39, 0x63, + 0xc3, 0x7a, 0x8c, 0x52, 0xd2, 0x31, 0xca, 0xbf, 0xc6, 0x94, 0xd3, 0x31, 0xc6, 0xc8, 0xd5, 0x20, + 0x49, 0x85, 0x12, 0x64, 0x73, 0x72, 0x3e, 0x50, 0x29, 0x7e, 0x11, 0xe9, 0xa0, 0x20, 0x0d, 0xe6, + 0xa4, 0x7b, 0xab, 0xb3, 0x2f, 0x03, 0x11, 0xc7, 0x82, 0xdb, 0xaf, 0xdc, 0xf7, 0x00, 0xef, 0x38, + 0x53, 0x8c, 0x46, 0xec, 0x0b, 0x92, 0x15, 0xb8, 0x2d, 0x15, 0x55, 0xe8, 0x54, 0xb6, 0x2a, 0x8f, + 0xda, 0x9e, 0x0d, 0xc8, 0x43, 0xe8, 0xc9, 0x53, 0x96, 0xf8, 0x09, 0x95, 0x32, 0x99, 0xa4, 0x54, + 0xa2, 0x53, 0xdd, 0xaa, 0x3c, 0x6a, 0x7a, 0x5d, 0x0d, 0x1f, 0xcd, 0x50, 0xb7, 0x03, 0xcb, 0x6f, + 0x50, 0xbd, 0x46, 0xaa, 0xb2, 0x14, 0xa5, 0xfb, 0x7d, 0x03, 0x9a, 0x45, 0x40, 0xee, 0xc2, 0xd2, + 0x19, 0xf2, 0x50, 0xa4, 0x66, 0xef, 0x96, 0x97, 0x47, 0x64, 0x1b, 0x3a, 0x31, 0xfd, 0xaf, 0x48, + 0xfd, 0x33, 0x4c, 0x25, 0x13, 0xdc, 0x6c, 0xdd, 0xf1, 0xda, 0x06, 0xfc, 0x64, 0x31, 0x43, 0x62, + 0xbc, 0x44, 0xaa, 0xe5, 0x24, 0x0d, 0x96, 0x48, 0x09, 0x55, 0xc1, 0x64, 0x46, 0xaa, 0x5b, 0x92, + 0x01, 0x0b, 0xd2, 0x43, 0xe8, 0x0d, 0x85, 0x50, 0x91, 0xa0, 0x21, 0xa6, 0x7e, 0x2c, 0x42, 0x74, + 0x6e, 0xdb, 0x5a, 0xe6, 0xf0, 0xa1, 0x08, 0x91, 0x6c, 0x40, 0x2b, 0xc4, 0x33, 0x16, 0xa0, 0xcf, + 0x42, 0x67, 0xc9, 0x1c, 0xb9, 0x69, 0x81, 0x77, 0x21, 0xd9, 0x81, 0x6e, 0xc2, 0xb8, 0xaf, 0x25, + 0xc4, 0x40, 0xe9, 0xdf, 0x6a, 0x98, 0x4d, 0x3a, 0x09, 0xe3, 0x47, 0x33, 0x90, 0xfc, 0x1d, 0x56, + 0xe7, 0x9a, 0x95, 0xd9, 0x4d, 0xc3, 0x5e, 0x99, 0x27, 0x4b, 0x1f, 0xdd, 0x83, 0x66, 0x44, 0xf9, + 0x38, 0xa3, 0x63, 0x74, 0x5a, 0xf6, 0x77, 0x8b, 0x58, 0xf7, 0x27, 0xa2, 0x43, 0x8c, 0x1c, 0x30, + 0x09, 0x1b, 0x90, 0x2d, 0x58, 0x66, 0xb3, 0x1e, 0x86, 0x4e, 0xdb, 0x6c, 0x5e, 0x86, 0xf4, 0x9e, + 0x29, 0x9e, 0x31, 0xa3, 0x4a, 0xc7, 0xb4, 0x76, 0x16, 0x2f, 0x28, 0x32, 0xa1, 0x72, 0xe2, 0x74, + 0x0d, 0xa5, 0xa4, 0xc8, 0x5b, 0x2a, 0x27, 0x7a, 0x13, 0x16, 0x27, 0x22, 0x55, 0x18, 0x3a, 0x3d, + 0xf3, 0x1b, 0xb3, 0x98, 0x6c, 0x02, 0x68, 0x41, 0x02, 0x1a, 0x4c, 0x30, 0x74, 0xfa, 0x26, 0xdb, + 0x4a, 0x18, 0xdf, 0x37, 0x00, 0x79, 0x02, 0x77, 0x4a, 0x42, 0xe4, 0xac, 0x3b, 0x86, 0xd5, 0x9f, + 0x27, 0x72, 0xf2, 0x63, 0xe8, 0x8f, 0x58, 0x1a, 0x9f, 0xd3, 0x54, 0x6b, 0x86, 0x12, 0xb9, 0x72, + 0x88, 0xe1, 0xf6, 0x0a, 0xfc, 0xc8, 0xc2, 0xe4, 0x01, 0xb4, 0x39, 0x62, 0x28, 0xfd, 0x21, 0x0d, + 0x4e, 0xb3, 0xc4, 0xf9, 0x83, 0x2d, 0xdd, 0x60, 0x2f, 0x0d, 0xa4, 0x25, 0x1b, 0x45, 0x74, 0x2c, + 0x9d, 0x15, 0xe3, 0x06, 0x1b, 0x68, 0x54, 0xf7, 0x3e, 0x72, 0x56, 0xad, 0x90, 0x26, 0x20, 0xeb, + 0xd0, 0x1c, 0x9d, 0xfb, 0xc6, 0x79, 0xce, 0x5d, 0x43, 0x6f, 0x8c, 0xce, 0x0f, 0x75, 0x58, 0xa4, + 0xb4, 0xdf, 0x9c, 0xb5, 0x59, 0x4a, 0x87, 0x79, 0xca, 0xb8, 0xcc, 0x71, 0x8a, 0xd4, 0x91, 0x0e, + 0xb5, 0x89, 0x46, 0xe7, 0x7e, 0xee, 0xfb, 0x75, 0xdb, 0xcc, 0xd1, 0xf9, 0x27, 0xeb, 0xfc, 0x3f, + 0x43, 0x77, 0x96, 0xf4, 0x4f, 0x71, 0x2a, 0x9d, 0x7b, 0x46, 0xf7, 0x76, 0xc1, 0x78, 0x8f, 0x53, + 0xa9, 0xa5, 0xcb, 0xf8, 0x88, 0x71, 0x26, 0x27, 0x18, 0x16, 0x75, 0x6e, 0x58, 0xe9, 0xe6, 0x89, + 0xbc, 0xd8, 0x0d, 0x68, 0x71, 0x51, 0x90, 0xfe, 0x68, 0x7b, 0xc4, 0x85, 0x4d, 0xba, 0x5d, 0x68, + 0xef, 0x47, 0x48, 0xd3, 0x63, 0x94, 0xba, 0xf1, 0xee, 0x77, 0x35, 0xe8, 0xec, 0x25, 0x49, 0x34, + 0x3d, 0x46, 0xa5, 0x18, 0x1f, 0xcb, 0x0b, 0xd6, 0xab, 0x5c, 0x67, 0xbd, 0x6a, 0xd9, 0x7a, 0x3b, + 0xd0, 0xcd, 0xb4, 0xb5, 0xe7, 0x93, 0xa1, 0x66, 0x2f, 0x42, 0x26, 0x71, 0x3e, 0x18, 0xc8, 0x9f, + 0x00, 0x26, 0x22, 0x46, 0x19, 0xa4, 0x88, 0xf6, 0x5e, 0xb6, 0xbd, 0x12, 0x42, 0xf8, 0x05, 0x7f, + 0x48, 0x91, 0xa5, 0x81, 0xbd, 0x97, 0xdd, 0xdd, 0xbd, 0xc1, 0x57, 0xe7, 0xda, 0xe0, 0x42, 0x05, + 0x83, 0xf9, 0x6f, 0x1e, 0x9b, 0x4d, 0x4e, 0xa6, 0x09, 0x96, 0x2d, 0x66, 0x51, 0xf2, 0x04, 0x08, + 0xcd, 0x94, 0xf0, 0x23, 0x11, 0x9c, 0xfa, 0x21, 0x46, 0x74, 0xea, 0xc7, 0xd2, 0xdc, 0xf2, 0x8e, + 0xd7, 0xd3, 0x99, 0x0f, 0x22, 0x38, 0x3d, 0xd0, 0xf8, 0xa1, 0xd4, 0x7e, 0x0c, 0x99, 0x4c, 0x34, + 0x29, 0x15, 0x8a, 0xce, 0xae, 0x7b, 0xc7, 0xeb, 0xe5, 0xb8, 0x97, 0xc3, 0xee, 0x53, 0x58, 0xb9, + 0xea, 0x04, 0xa4, 0x01, 0xb5, 0xbd, 0xe3, 0xf7, 0xfd, 0x5b, 0x04, 0x60, 0xe9, 0xe0, 0xd5, 0xa7, + 0x77, 0xfb, 0xaf, 0xfa, 0x15, 0xd2, 0x84, 0xfa, 0xdb, 0x7f, 0x1d, 0x9f, 0xf4, 0xab, 0xae, 0x0b, + 0x60, 0xca, 0x78, 0x5d, 0x78, 0xd3, 0x3a, 0xb6, 0x52, 0x72, 0xac, 0xbb, 0x0d, 0xad, 0xfd, 0x09, + 0xe5, 0x63, 0x3c, 0x62, 0x5c, 0x0f, 0xd3, 0x14, 0x63, 0x71, 0x66, 0xdb, 0xd4, 0xf4, 0xf2, 0xc8, + 0xfd, 0xa1, 0x02, 0xf5, 0x23, 0xc6, 0xc7, 0xc4, 0x81, 0x46, 0x2e, 0x56, 0xde, 0xc8, 0x22, 0xd4, + 0x7e, 0x1a, 0x66, 0x4a, 0x89, 0x0b, 0xd3, 0xcb, 0x8e, 0xf3, 0xbe, 0x4d, 0x94, 0x66, 0xd1, 0xe5, + 0x39, 0x57, 0xfb, 0xa6, 0x39, 0x57, 0xbf, 0x7e, 0xce, 0xb9, 0x4d, 0x58, 0xda, 0xa7, 0x3c, 0xc0, + 0xc8, 0xdd, 0x02, 0x78, 0x83, 0xea, 0x15, 0x57, 0xa9, 0x48, 0xa6, 0x84, 0x40, 0x5d, 0xb2, 0x2f, + 0xfa, 0xdc, 0xd5, 0x47, 0x1d, 0xcf, 0xac, 0xdd, 0x6d, 0x68, 0x14, 0x69, 0x07, 0x1a, 0x68, 0x97, + 0x86, 0xd1, 0xf6, 0x8a, 0xd0, 0x6d, 0x03, 0x7c, 0x66, 0x09, 0x1e, 0x98, 0x21, 0xed, 0xfe, 0x58, + 0x05, 0xf8, 0x20, 0x68, 0x68, 0x43, 0x6d, 0xed, 0x98, 0x63, 0x2c, 0x38, 0x0b, 0x0a, 0x6b, 0x17, + 0x31, 0x79, 0x0e, 0x75, 0xae, 0x1f, 0x02, 0xad, 0xc2, 0xf2, 0xee, 0xce, 0x55, 0x86, 0xcb, 0xdf, + 0xcc, 0xb7, 0x07, 0x1f, 0x45, 0x68, 0x4d, 0x65, 0x3e, 0x21, 0x7d, 0xa8, 0x25, 0xcc, 0xaa, 0xd2, + 0xf2, 0xf4, 0xf2, 0x37, 0x69, 0x41, 0xb6, 0x4b, 0x17, 0x4f, 0xdb, 0xbe, 0xf5, 0xa2, 0x81, 0x7c, + 0x1c, 0x31, 0x39, 0xb9, 0xea, 0x06, 0x2e, 0x95, 0x6f, 0xe0, 0x36, 0x74, 0xcc, 0xe3, 0x1c, 0x4c, + 0x30, 0x38, 0x95, 0x59, 0x9c, 0xbf, 0x44, 0x6d, 0x0d, 0xee, 0xe7, 0x18, 0xb9, 0x0f, 0xcb, 0xd9, + 0xee, 0xc8, 0x0f, 0x44, 0xc6, 0x15, 0xa6, 0xe6, 0xf9, 0xe9, 0x78, 0x90, 0xed, 0x8e, 0xf6, 0x2d, + 0xe2, 0xfe, 0x5c, 0x85, 0x65, 0x0f, 0x25, 0xaa, 0x5c, 0xae, 0x1d, 0xe8, 0xce, 0x3c, 0x4f, 0x79, + 0x28, 0xe2, 0xdc, 0x68, 0x9d, 0xc2, 0xf1, 0x06, 0x24, 0xf7, 0xa1, 0x29, 0x55, 0x8a, 0x7c, 0xac, + 0x26, 0xf6, 0xdd, 0x7e, 0x51, 0xdb, 0x7d, 0xfa, 0xcc, 0x9b, 0x81, 0xd7, 0xab, 0x51, 0xfb, 0x8a, + 0x1a, 0x97, 0x5d, 0x57, 0xbf, 0xca, 0x75, 0xbf, 0x43, 0xb4, 0x05, 0x3d, 0x1a, 0x8b, 0x7a, 0x68, + 0x82, 0x51, 0x35, 0x1f, 0xa5, 0xf6, 0xbd, 0x06, 0x0d, 0x5d, 0x35, 0x69, 0x5b, 0x97, 0x27, 0xad, + 0x5d, 0xe5, 0x5e, 0xec, 0x43, 0x37, 0xb7, 0xaf, 0x87, 0xff, 0xcb, 0x50, 0x2a, 0xf7, 0x2f, 0x00, + 0x39, 0xb2, 0x17, 0x9c, 0x5e, 0xf4, 0x74, 0xa5, 0xec, 0xe9, 0x5f, 0x6a, 0xd0, 0xf5, 0x30, 0x10, + 0x67, 0x98, 0x4e, 0xf3, 0xd6, 0x6c, 0x02, 0x9c, 0x8b, 0x34, 0xb4, 0x87, 0xcf, 0x67, 0x44, 0x4b, + 0x23, 0xe6, 0xec, 0xd7, 0x2b, 0x5e, 0xfd, 0x26, 0xc5, 0x6b, 0x37, 0x29, 0x5e, 0xbf, 0x51, 0xf1, + 0xdb, 0x65, 0xc5, 0x1f, 0x43, 0x1f, 0xf9, 0x48, 0xa4, 0x01, 0xfa, 0xfa, 0xac, 0x11, 0x93, 0xca, + 0xb4, 0xa4, 0xe9, 0xf5, 0x72, 0xfc, 0x73, 0x0e, 0x93, 0x13, 0xa8, 0xab, 0x69, 0x82, 0x46, 0xf4, + 0xee, 0xee, 0x3f, 0x6f, 0x98, 0xff, 0x17, 0xd5, 0x59, 0x08, 0xed, 0x4d, 0xd5, 0xbb, 0x2d, 0xb6, + 0xbc, 0x75, 0xa9, 0xe5, 0x6b, 0xd0, 0x08, 0xd3, 0xa9, 0x9f, 0x66, 0xdc, 0xfc, 0x75, 0xd5, 0xf4, + 0x96, 0xc2, 0x74, 0xea, 0x65, 0xdc, 0xfd, 0x0f, 0x90, 0xcb, 0xbb, 0x92, 0x1d, 0x78, 0x70, 0x19, + 0xf5, 0x8f, 0x83, 0x94, 0xc6, 0xc3, 0x08, 0x43, 0x5d, 0x8d, 0xec, 0xdf, 0x22, 0x9b, 0xb0, 0x7e, + 0x05, 0xed, 0x90, 0xaa, 0x94, 0xfd, 0xbf, 0x5f, 0x71, 0x7f, 0xaa, 0xc0, 0xb2, 0xa6, 0xe6, 0xbe, + 0x20, 0x1f, 0xf3, 0xda, 0x2b, 0xa6, 0xf6, 0x17, 0x37, 0xd4, 0x5e, 0xfa, 0xb2, 0xbc, 0x9e, 0x57, + 0xed, 0x8e, 0xa0, 0xb7, 0x90, 0x20, 0xeb, 0xb0, 0xba, 0x00, 0xf9, 0x47, 0x11, 0x65, 0xbc, 0x7f, + 0x8b, 0x6c, 0xc0, 0xda, 0x62, 0xca, 0x9e, 0xf4, 0x79, 0xbf, 0x72, 0x7d, 0xf2, 0x59, 0xbf, 0xea, + 0x6e, 0x42, 0x43, 0x27, 0xb5, 0x99, 0x09, 0xd4, 0x75, 0x87, 0xcd, 0x74, 0x6e, 0x79, 0x66, 0xed, + 0xfe, 0x0d, 0x3a, 0xc7, 0xa8, 0xfe, 0xbd, 0xfb, 0xba, 0x74, 0xbf, 0xca, 0xdd, 0xa8, 0x2c, 0x76, + 0xe3, 0xe5, 0x3f, 0x60, 0x3b, 0x10, 0xf1, 0x40, 0x52, 0x25, 0xe4, 0x84, 0x45, 0x74, 0x28, 0x0b, + 0x21, 0x22, 0x36, 0xb4, 0xff, 0xbb, 0x0c, 0xb3, 0xd1, 0xcb, 0xb5, 0x13, 0x03, 0x1e, 0x5a, 0x71, + 0x0e, 0x67, 0xd2, 0xfc, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x6e, 0xfc, 0x59, 0x29, 0x0d, 0x00, + 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.proto new file mode 100644 index 000000000..0ab825a1b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages-management.proto @@ -0,0 +1,289 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto +// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. + +syntax = "proto2"; +package hw.trezor.messages.management; + +// Sugar for easier handling in Java +option java_package = "com.satoshilabs.trezor.lib.protobuf"; +option java_outer_classname = "TrezorMessageManagement"; + +import "messages-common.proto"; + +/** + * Request: Reset device to default state and ask for device details + * @start + * @next Features + */ +message Initialize { + optional bytes state = 1; // assumed device state, clear session if set and different + optional bool skip_passphrase = 2; // this session should always assume empty passphrase +} + +/** + * Request: Ask for device details (no device reset) + * @start + * @next Features + */ +message GetFeatures { +} + +/** + * Response: Reports various information about the device + * @end + */ +message Features { + optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io" + optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1 + optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0 + optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0 + optional bool bootloader_mode = 5; // is device in bootloader mode? + optional string device_id = 6; // device's unique identifier + optional bool pin_protection = 7; // is device protected by PIN? + optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase? + optional string language = 9; // device language + optional string label = 10; // device description label + optional bool initialized = 12; // does device contain seed? + optional bytes revision = 13; // SCM revision of firmware + optional bytes bootloader_hash = 14; // hash of the bootloader + optional bool imported = 15; // was storage imported from an external source? + optional bool pin_cached = 16; // is PIN already cached in session? + optional bool passphrase_cached = 17; // is passphrase already cached in session? + optional bool firmware_present = 18; // is valid firmware loaded? + optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup) + optional uint32 flags = 20; // device flags (equals to Storage.flags) + optional string model = 21; // device hardware model + optional uint32 fw_major = 22; // reported firmware version if in bootloader mode + optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode + optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode + optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode + optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash) + optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup) + optional bool no_backup = 28; // report no backup (equals to Storage.no_backup) +} + +/** + * Request: clear session (removes cached PIN, passphrase, etc). + * @start + * @next Success + */ +message ClearSession { +} + +/** + * Request: change language and/or label of the device + * @start + * @next Success + * @next Failure + */ +message ApplySettings { + optional string language = 1; + optional string label = 2; + optional bool use_passphrase = 3; + optional bytes homescreen = 4; + optional PassphraseSourceType passphrase_source = 5; + optional uint32 auto_lock_delay_ms = 6; + optional uint32 display_rotation = 7; // in degrees from North + /** + * Structure representing passphrase source + */ + enum PassphraseSourceType { + ASK = 0; + DEVICE = 1; + HOST = 2; + } +} + +/** + * Request: set flags of the device + * @start + * @next Success + * @next Failure + */ +message ApplyFlags { + optional uint32 flags = 1; // bitmask, can only set bits, not unset +} + +/** + * Request: Starts workflow for setting/changing/removing the PIN + * @start + * @next Success + * @next Failure + */ +message ChangePin { + optional bool remove = 1; // is PIN removal requested? +} + +/** + * Request: Test if the device is alive, device sends back the message in Success response + * @start + * @next Success + */ +message Ping { + optional string message = 1; // message to send back in Success message + optional bool button_protection = 2; // ask for button press + optional bool pin_protection = 3; // ask for PIN if set in device + optional bool passphrase_protection = 4; // ask for passphrase if set in device +} + +/** + * Request: Abort last operation that required user interaction + * @start + * @next Failure + */ +message Cancel { +} + +/** + * Request: Request a sample of random data generated by hardware RNG. May be used for testing. + * @start + * @next Entropy + * @next Failure + */ +message GetEntropy { + required uint32 size = 1; // size of requested entropy +} + +/** + * Response: Reply with random data generated by internal RNG + * @end + */ +message Entropy { + required bytes entropy = 1; // chunk of random generated bytes +} + +/** + * Request: Request device to wipe all sensitive data and settings + * @start + * @next Success + * @next Failure + */ +message WipeDevice { +} + +/** + * Request: Load seed and related internal settings from the computer + * @start + * @next Success + * @next Failure + */ +message LoadDevice { + optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words) + optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node + optional string pin = 3; // set PIN protection + optional bool passphrase_protection = 4; // enable master node encryption using passphrase + optional string language = 5 [default='english']; // device language + optional string label = 6; // device label + optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum + optional uint32 u2f_counter = 8; // U2F counter +} + +/** + * Request: Ask device to do initialization involving user interaction + * @start + * @next EntropyRequest + * @next Failure + */ +message ResetDevice { + optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy + optional uint32 strength = 2 [default=256]; // strength of seed in bits + optional bool passphrase_protection = 3; // enable master node encryption using passphrase + optional bool pin_protection = 4; // enable PIN protection + optional string language = 5 [default='english']; // device language + optional string label = 6; // device label + optional uint32 u2f_counter = 7; // U2F counter + optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow + optional bool no_backup = 9; // indicate that no backup is going to be made +} + +/** + * Request: Perform backup of the device seed if not backed up using ResetDevice + * @start + * @next Success + */ +message BackupDevice { +} + +/** + * Response: Ask for additional entropy from host computer + * @next EntropyAck + */ +message EntropyRequest { +} + +/** + * Request: Provide additional entropy for seed generation function + * @next Success + */ +message EntropyAck { + optional bytes entropy = 1; // 256 bits (32 bytes) of random data +} + +/** + * Request: Start recovery workflow asking user for specific words of mnemonic + * Used to recovery device safely even on untrusted computer. + * @start + * @next WordRequest + */ +message RecoveryDevice { + optional uint32 word_count = 1; // number of words in BIP-39 mnemonic + optional bool passphrase_protection = 2; // enable master node encryption using passphrase + optional bool pin_protection = 3; // enable PIN protection + optional string language = 4 [default='english']; // device language + optional string label = 5; // device label + optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process + // 7 reserved for unused recovery method + optional RecoveryDeviceType type = 8; // supported recovery type + optional uint32 u2f_counter = 9; // U2F counter + optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation) + /** + * Type of recovery procedure. These should be used as bitmask, e.g., + * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` + * listing every method supported by the host computer. + * + * Note that ScrambledWords must be supported by every implementation + * for backward compatibility; there is no way to not support it. + */ + enum RecoveryDeviceType { + // use powers of two when extending this field + RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order + RecoveryDeviceType_Matrix = 1; // matrix recovery type + } +} + +/** + * Response: Device is waiting for user to enter word of the mnemonic + * Its position is shown only on device's internal display. + * @next WordAck + */ +message WordRequest { + optional WordRequestType type = 1; + /** + * Type of Recovery Word request + */ + enum WordRequestType { + WordRequestType_Plain = 0; + WordRequestType_Matrix9 = 1; + WordRequestType_Matrix6 = 2; + } +} + +/** + * Request: Computer replies with word from the mnemonic + * @next WordRequest + * @next Success + * @next Failure + */ +message WordAck { + required string word = 1; // one word of mnemonic on asked position +} + +/** + * Request: Set U2F counter + * @start + * @next Success + */ +message SetU2FCounter { + optional uint32 u2f_counter = 1; // counter +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go new file mode 100644 index 000000000..6278bd8ee --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.pb.go @@ -0,0 +1,889 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: messages.proto + +package trezor + +import ( + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" + descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +//* +// Mapping between TREZOR wire identifier (uint) and a protobuf message +type MessageType int32 + +const ( + // Management + MessageType_MessageType_Initialize MessageType = 0 + MessageType_MessageType_Ping MessageType = 1 + MessageType_MessageType_Success MessageType = 2 + MessageType_MessageType_Failure MessageType = 3 + MessageType_MessageType_ChangePin MessageType = 4 + MessageType_MessageType_WipeDevice MessageType = 5 + MessageType_MessageType_GetEntropy MessageType = 9 + MessageType_MessageType_Entropy MessageType = 10 + MessageType_MessageType_LoadDevice MessageType = 13 + MessageType_MessageType_ResetDevice MessageType = 14 + MessageType_MessageType_Features MessageType = 17 + MessageType_MessageType_PinMatrixRequest MessageType = 18 + MessageType_MessageType_PinMatrixAck MessageType = 19 + MessageType_MessageType_Cancel MessageType = 20 + MessageType_MessageType_ClearSession MessageType = 24 + MessageType_MessageType_ApplySettings MessageType = 25 + MessageType_MessageType_ButtonRequest MessageType = 26 + MessageType_MessageType_ButtonAck MessageType = 27 + MessageType_MessageType_ApplyFlags MessageType = 28 + MessageType_MessageType_BackupDevice MessageType = 34 + MessageType_MessageType_EntropyRequest MessageType = 35 + MessageType_MessageType_EntropyAck MessageType = 36 + MessageType_MessageType_PassphraseRequest MessageType = 41 + MessageType_MessageType_PassphraseAck MessageType = 42 + MessageType_MessageType_PassphraseStateRequest MessageType = 77 + MessageType_MessageType_PassphraseStateAck MessageType = 78 + MessageType_MessageType_RecoveryDevice MessageType = 45 + MessageType_MessageType_WordRequest MessageType = 46 + MessageType_MessageType_WordAck MessageType = 47 + MessageType_MessageType_GetFeatures MessageType = 55 + MessageType_MessageType_SetU2FCounter MessageType = 63 + // Bootloader + MessageType_MessageType_FirmwareErase MessageType = 6 + MessageType_MessageType_FirmwareUpload MessageType = 7 + MessageType_MessageType_FirmwareRequest MessageType = 8 + MessageType_MessageType_SelfTest MessageType = 32 + // Bitcoin + MessageType_MessageType_GetPublicKey MessageType = 11 + MessageType_MessageType_PublicKey MessageType = 12 + MessageType_MessageType_SignTx MessageType = 15 + MessageType_MessageType_TxRequest MessageType = 21 + MessageType_MessageType_TxAck MessageType = 22 + MessageType_MessageType_GetAddress MessageType = 29 + MessageType_MessageType_Address MessageType = 30 + MessageType_MessageType_SignMessage MessageType = 38 + MessageType_MessageType_VerifyMessage MessageType = 39 + MessageType_MessageType_MessageSignature MessageType = 40 + // Crypto + MessageType_MessageType_CipherKeyValue MessageType = 23 + MessageType_MessageType_CipheredKeyValue MessageType = 48 + MessageType_MessageType_SignIdentity MessageType = 53 + MessageType_MessageType_SignedIdentity MessageType = 54 + MessageType_MessageType_GetECDHSessionKey MessageType = 61 + MessageType_MessageType_ECDHSessionKey MessageType = 62 + MessageType_MessageType_CosiCommit MessageType = 71 + MessageType_MessageType_CosiCommitment MessageType = 72 + MessageType_MessageType_CosiSign MessageType = 73 + MessageType_MessageType_CosiSignature MessageType = 74 + // Debug + MessageType_MessageType_DebugLinkDecision MessageType = 100 + MessageType_MessageType_DebugLinkGetState MessageType = 101 + MessageType_MessageType_DebugLinkState MessageType = 102 + MessageType_MessageType_DebugLinkStop MessageType = 103 + MessageType_MessageType_DebugLinkLog MessageType = 104 + MessageType_MessageType_DebugLinkMemoryRead MessageType = 110 + MessageType_MessageType_DebugLinkMemory MessageType = 111 + MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112 + MessageType_MessageType_DebugLinkFlashErase MessageType = 113 + // Ethereum + MessageType_MessageType_EthereumGetPublicKey MessageType = 450 + MessageType_MessageType_EthereumPublicKey MessageType = 451 + MessageType_MessageType_EthereumGetAddress MessageType = 56 + MessageType_MessageType_EthereumAddress MessageType = 57 + MessageType_MessageType_EthereumSignTx MessageType = 58 + MessageType_MessageType_EthereumTxRequest MessageType = 59 + MessageType_MessageType_EthereumTxAck MessageType = 60 + MessageType_MessageType_EthereumSignMessage MessageType = 64 + MessageType_MessageType_EthereumVerifyMessage MessageType = 65 + MessageType_MessageType_EthereumMessageSignature MessageType = 66 + // NEM + MessageType_MessageType_NEMGetAddress MessageType = 67 + MessageType_MessageType_NEMAddress MessageType = 68 + MessageType_MessageType_NEMSignTx MessageType = 69 + MessageType_MessageType_NEMSignedTx MessageType = 70 + MessageType_MessageType_NEMDecryptMessage MessageType = 75 + MessageType_MessageType_NEMDecryptedMessage MessageType = 76 + // Lisk + MessageType_MessageType_LiskGetAddress MessageType = 114 + MessageType_MessageType_LiskAddress MessageType = 115 + MessageType_MessageType_LiskSignTx MessageType = 116 + MessageType_MessageType_LiskSignedTx MessageType = 117 + MessageType_MessageType_LiskSignMessage MessageType = 118 + MessageType_MessageType_LiskMessageSignature MessageType = 119 + MessageType_MessageType_LiskVerifyMessage MessageType = 120 + MessageType_MessageType_LiskGetPublicKey MessageType = 121 + MessageType_MessageType_LiskPublicKey MessageType = 122 + // Tezos + MessageType_MessageType_TezosGetAddress MessageType = 150 + MessageType_MessageType_TezosAddress MessageType = 151 + MessageType_MessageType_TezosSignTx MessageType = 152 + MessageType_MessageType_TezosSignedTx MessageType = 153 + MessageType_MessageType_TezosGetPublicKey MessageType = 154 + MessageType_MessageType_TezosPublicKey MessageType = 155 + // Stellar + MessageType_MessageType_StellarSignTx MessageType = 202 + MessageType_MessageType_StellarTxOpRequest MessageType = 203 + MessageType_MessageType_StellarGetAddress MessageType = 207 + MessageType_MessageType_StellarAddress MessageType = 208 + MessageType_MessageType_StellarCreateAccountOp MessageType = 210 + MessageType_MessageType_StellarPaymentOp MessageType = 211 + MessageType_MessageType_StellarPathPaymentOp MessageType = 212 + MessageType_MessageType_StellarManageOfferOp MessageType = 213 + MessageType_MessageType_StellarCreatePassiveOfferOp MessageType = 214 + MessageType_MessageType_StellarSetOptionsOp MessageType = 215 + MessageType_MessageType_StellarChangeTrustOp MessageType = 216 + MessageType_MessageType_StellarAllowTrustOp MessageType = 217 + MessageType_MessageType_StellarAccountMergeOp MessageType = 218 + // omitted: StellarInflationOp is not a supported operation, would be 219 + MessageType_MessageType_StellarManageDataOp MessageType = 220 + MessageType_MessageType_StellarBumpSequenceOp MessageType = 221 + MessageType_MessageType_StellarSignedTx MessageType = 230 + // TRON + MessageType_MessageType_TronGetAddress MessageType = 250 + MessageType_MessageType_TronAddress MessageType = 251 + MessageType_MessageType_TronSignTx MessageType = 252 + MessageType_MessageType_TronSignedTx MessageType = 253 + // Cardano + // dropped Sign/VerifyMessage ids 300-302 + MessageType_MessageType_CardanoSignTx MessageType = 303 + MessageType_MessageType_CardanoTxRequest MessageType = 304 + MessageType_MessageType_CardanoGetPublicKey MessageType = 305 + MessageType_MessageType_CardanoPublicKey MessageType = 306 + MessageType_MessageType_CardanoGetAddress MessageType = 307 + MessageType_MessageType_CardanoAddress MessageType = 308 + MessageType_MessageType_CardanoTxAck MessageType = 309 + MessageType_MessageType_CardanoSignedTx MessageType = 310 + // Ontology + MessageType_MessageType_OntologyGetAddress MessageType = 350 + MessageType_MessageType_OntologyAddress MessageType = 351 + MessageType_MessageType_OntologyGetPublicKey MessageType = 352 + MessageType_MessageType_OntologyPublicKey MessageType = 353 + MessageType_MessageType_OntologySignTransfer MessageType = 354 + MessageType_MessageType_OntologySignedTransfer MessageType = 355 + MessageType_MessageType_OntologySignWithdrawOng MessageType = 356 + MessageType_MessageType_OntologySignedWithdrawOng MessageType = 357 + MessageType_MessageType_OntologySignOntIdRegister MessageType = 358 + MessageType_MessageType_OntologySignedOntIdRegister MessageType = 359 + MessageType_MessageType_OntologySignOntIdAddAttributes MessageType = 360 + MessageType_MessageType_OntologySignedOntIdAddAttributes MessageType = 361 + // Ripple + MessageType_MessageType_RippleGetAddress MessageType = 400 + MessageType_MessageType_RippleAddress MessageType = 401 + MessageType_MessageType_RippleSignTx MessageType = 402 + MessageType_MessageType_RippleSignedTx MessageType = 403 + // Monero + MessageType_MessageType_MoneroTransactionInitRequest MessageType = 501 + MessageType_MessageType_MoneroTransactionInitAck MessageType = 502 + MessageType_MessageType_MoneroTransactionSetInputRequest MessageType = 503 + MessageType_MessageType_MoneroTransactionSetInputAck MessageType = 504 + MessageType_MessageType_MoneroTransactionInputsPermutationRequest MessageType = 505 + MessageType_MessageType_MoneroTransactionInputsPermutationAck MessageType = 506 + MessageType_MessageType_MoneroTransactionInputViniRequest MessageType = 507 + MessageType_MessageType_MoneroTransactionInputViniAck MessageType = 508 + MessageType_MessageType_MoneroTransactionAllInputsSetRequest MessageType = 509 + MessageType_MessageType_MoneroTransactionAllInputsSetAck MessageType = 510 + MessageType_MessageType_MoneroTransactionSetOutputRequest MessageType = 511 + MessageType_MessageType_MoneroTransactionSetOutputAck MessageType = 512 + MessageType_MessageType_MoneroTransactionAllOutSetRequest MessageType = 513 + MessageType_MessageType_MoneroTransactionAllOutSetAck MessageType = 514 + MessageType_MessageType_MoneroTransactionSignInputRequest MessageType = 515 + MessageType_MessageType_MoneroTransactionSignInputAck MessageType = 516 + MessageType_MessageType_MoneroTransactionFinalRequest MessageType = 517 + MessageType_MessageType_MoneroTransactionFinalAck MessageType = 518 + MessageType_MessageType_MoneroKeyImageExportInitRequest MessageType = 530 + MessageType_MessageType_MoneroKeyImageExportInitAck MessageType = 531 + MessageType_MessageType_MoneroKeyImageSyncStepRequest MessageType = 532 + MessageType_MessageType_MoneroKeyImageSyncStepAck MessageType = 533 + MessageType_MessageType_MoneroKeyImageSyncFinalRequest MessageType = 534 + MessageType_MessageType_MoneroKeyImageSyncFinalAck MessageType = 535 + MessageType_MessageType_MoneroGetAddress MessageType = 540 + MessageType_MessageType_MoneroAddress MessageType = 541 + MessageType_MessageType_MoneroGetWatchKey MessageType = 542 + MessageType_MessageType_MoneroWatchKey MessageType = 543 + MessageType_MessageType_DebugMoneroDiagRequest MessageType = 546 + MessageType_MessageType_DebugMoneroDiagAck MessageType = 547 + MessageType_MessageType_MoneroGetTxKeyRequest MessageType = 550 + MessageType_MessageType_MoneroGetTxKeyAck MessageType = 551 + MessageType_MessageType_MoneroLiveRefreshStartRequest MessageType = 552 + MessageType_MessageType_MoneroLiveRefreshStartAck MessageType = 553 + MessageType_MessageType_MoneroLiveRefreshStepRequest MessageType = 554 + MessageType_MessageType_MoneroLiveRefreshStepAck MessageType = 555 + MessageType_MessageType_MoneroLiveRefreshFinalRequest MessageType = 556 + MessageType_MessageType_MoneroLiveRefreshFinalAck MessageType = 557 + // EOS + MessageType_MessageType_EosGetPublicKey MessageType = 600 + MessageType_MessageType_EosPublicKey MessageType = 601 + MessageType_MessageType_EosSignTx MessageType = 602 + MessageType_MessageType_EosTxActionRequest MessageType = 603 + MessageType_MessageType_EosTxActionAck MessageType = 604 + MessageType_MessageType_EosSignedTx MessageType = 605 + // Binance + MessageType_MessageType_BinanceGetAddress MessageType = 700 + MessageType_MessageType_BinanceAddress MessageType = 701 + MessageType_MessageType_BinanceGetPublicKey MessageType = 702 + MessageType_MessageType_BinancePublicKey MessageType = 703 + MessageType_MessageType_BinanceSignTx MessageType = 704 + MessageType_MessageType_BinanceTxRequest MessageType = 705 + MessageType_MessageType_BinanceTransferMsg MessageType = 706 + MessageType_MessageType_BinanceOrderMsg MessageType = 707 + MessageType_MessageType_BinanceCancelMsg MessageType = 708 + MessageType_MessageType_BinanceSignedTx MessageType = 709 +) + +var MessageType_name = map[int32]string{ + 0: "MessageType_Initialize", + 1: "MessageType_Ping", + 2: "MessageType_Success", + 3: "MessageType_Failure", + 4: "MessageType_ChangePin", + 5: "MessageType_WipeDevice", + 9: "MessageType_GetEntropy", + 10: "MessageType_Entropy", + 13: "MessageType_LoadDevice", + 14: "MessageType_ResetDevice", + 17: "MessageType_Features", + 18: "MessageType_PinMatrixRequest", + 19: "MessageType_PinMatrixAck", + 20: "MessageType_Cancel", + 24: "MessageType_ClearSession", + 25: "MessageType_ApplySettings", + 26: "MessageType_ButtonRequest", + 27: "MessageType_ButtonAck", + 28: "MessageType_ApplyFlags", + 34: "MessageType_BackupDevice", + 35: "MessageType_EntropyRequest", + 36: "MessageType_EntropyAck", + 41: "MessageType_PassphraseRequest", + 42: "MessageType_PassphraseAck", + 77: "MessageType_PassphraseStateRequest", + 78: "MessageType_PassphraseStateAck", + 45: "MessageType_RecoveryDevice", + 46: "MessageType_WordRequest", + 47: "MessageType_WordAck", + 55: "MessageType_GetFeatures", + 63: "MessageType_SetU2FCounter", + 6: "MessageType_FirmwareErase", + 7: "MessageType_FirmwareUpload", + 8: "MessageType_FirmwareRequest", + 32: "MessageType_SelfTest", + 11: "MessageType_GetPublicKey", + 12: "MessageType_PublicKey", + 15: "MessageType_SignTx", + 21: "MessageType_TxRequest", + 22: "MessageType_TxAck", + 29: "MessageType_GetAddress", + 30: "MessageType_Address", + 38: "MessageType_SignMessage", + 39: "MessageType_VerifyMessage", + 40: "MessageType_MessageSignature", + 23: "MessageType_CipherKeyValue", + 48: "MessageType_CipheredKeyValue", + 53: "MessageType_SignIdentity", + 54: "MessageType_SignedIdentity", + 61: "MessageType_GetECDHSessionKey", + 62: "MessageType_ECDHSessionKey", + 71: "MessageType_CosiCommit", + 72: "MessageType_CosiCommitment", + 73: "MessageType_CosiSign", + 74: "MessageType_CosiSignature", + 100: "MessageType_DebugLinkDecision", + 101: "MessageType_DebugLinkGetState", + 102: "MessageType_DebugLinkState", + 103: "MessageType_DebugLinkStop", + 104: "MessageType_DebugLinkLog", + 110: "MessageType_DebugLinkMemoryRead", + 111: "MessageType_DebugLinkMemory", + 112: "MessageType_DebugLinkMemoryWrite", + 113: "MessageType_DebugLinkFlashErase", + 450: "MessageType_EthereumGetPublicKey", + 451: "MessageType_EthereumPublicKey", + 56: "MessageType_EthereumGetAddress", + 57: "MessageType_EthereumAddress", + 58: "MessageType_EthereumSignTx", + 59: "MessageType_EthereumTxRequest", + 60: "MessageType_EthereumTxAck", + 64: "MessageType_EthereumSignMessage", + 65: "MessageType_EthereumVerifyMessage", + 66: "MessageType_EthereumMessageSignature", + 67: "MessageType_NEMGetAddress", + 68: "MessageType_NEMAddress", + 69: "MessageType_NEMSignTx", + 70: "MessageType_NEMSignedTx", + 75: "MessageType_NEMDecryptMessage", + 76: "MessageType_NEMDecryptedMessage", + 114: "MessageType_LiskGetAddress", + 115: "MessageType_LiskAddress", + 116: "MessageType_LiskSignTx", + 117: "MessageType_LiskSignedTx", + 118: "MessageType_LiskSignMessage", + 119: "MessageType_LiskMessageSignature", + 120: "MessageType_LiskVerifyMessage", + 121: "MessageType_LiskGetPublicKey", + 122: "MessageType_LiskPublicKey", + 150: "MessageType_TezosGetAddress", + 151: "MessageType_TezosAddress", + 152: "MessageType_TezosSignTx", + 153: "MessageType_TezosSignedTx", + 154: "MessageType_TezosGetPublicKey", + 155: "MessageType_TezosPublicKey", + 202: "MessageType_StellarSignTx", + 203: "MessageType_StellarTxOpRequest", + 207: "MessageType_StellarGetAddress", + 208: "MessageType_StellarAddress", + 210: "MessageType_StellarCreateAccountOp", + 211: "MessageType_StellarPaymentOp", + 212: "MessageType_StellarPathPaymentOp", + 213: "MessageType_StellarManageOfferOp", + 214: "MessageType_StellarCreatePassiveOfferOp", + 215: "MessageType_StellarSetOptionsOp", + 216: "MessageType_StellarChangeTrustOp", + 217: "MessageType_StellarAllowTrustOp", + 218: "MessageType_StellarAccountMergeOp", + 220: "MessageType_StellarManageDataOp", + 221: "MessageType_StellarBumpSequenceOp", + 230: "MessageType_StellarSignedTx", + 250: "MessageType_TronGetAddress", + 251: "MessageType_TronAddress", + 252: "MessageType_TronSignTx", + 253: "MessageType_TronSignedTx", + 303: "MessageType_CardanoSignTx", + 304: "MessageType_CardanoTxRequest", + 305: "MessageType_CardanoGetPublicKey", + 306: "MessageType_CardanoPublicKey", + 307: "MessageType_CardanoGetAddress", + 308: "MessageType_CardanoAddress", + 309: "MessageType_CardanoTxAck", + 310: "MessageType_CardanoSignedTx", + 350: "MessageType_OntologyGetAddress", + 351: "MessageType_OntologyAddress", + 352: "MessageType_OntologyGetPublicKey", + 353: "MessageType_OntologyPublicKey", + 354: "MessageType_OntologySignTransfer", + 355: "MessageType_OntologySignedTransfer", + 356: "MessageType_OntologySignWithdrawOng", + 357: "MessageType_OntologySignedWithdrawOng", + 358: "MessageType_OntologySignOntIdRegister", + 359: "MessageType_OntologySignedOntIdRegister", + 360: "MessageType_OntologySignOntIdAddAttributes", + 361: "MessageType_OntologySignedOntIdAddAttributes", + 400: "MessageType_RippleGetAddress", + 401: "MessageType_RippleAddress", + 402: "MessageType_RippleSignTx", + 403: "MessageType_RippleSignedTx", + 501: "MessageType_MoneroTransactionInitRequest", + 502: "MessageType_MoneroTransactionInitAck", + 503: "MessageType_MoneroTransactionSetInputRequest", + 504: "MessageType_MoneroTransactionSetInputAck", + 505: "MessageType_MoneroTransactionInputsPermutationRequest", + 506: "MessageType_MoneroTransactionInputsPermutationAck", + 507: "MessageType_MoneroTransactionInputViniRequest", + 508: "MessageType_MoneroTransactionInputViniAck", + 509: "MessageType_MoneroTransactionAllInputsSetRequest", + 510: "MessageType_MoneroTransactionAllInputsSetAck", + 511: "MessageType_MoneroTransactionSetOutputRequest", + 512: "MessageType_MoneroTransactionSetOutputAck", + 513: "MessageType_MoneroTransactionAllOutSetRequest", + 514: "MessageType_MoneroTransactionAllOutSetAck", + 515: "MessageType_MoneroTransactionSignInputRequest", + 516: "MessageType_MoneroTransactionSignInputAck", + 517: "MessageType_MoneroTransactionFinalRequest", + 518: "MessageType_MoneroTransactionFinalAck", + 530: "MessageType_MoneroKeyImageExportInitRequest", + 531: "MessageType_MoneroKeyImageExportInitAck", + 532: "MessageType_MoneroKeyImageSyncStepRequest", + 533: "MessageType_MoneroKeyImageSyncStepAck", + 534: "MessageType_MoneroKeyImageSyncFinalRequest", + 535: "MessageType_MoneroKeyImageSyncFinalAck", + 540: "MessageType_MoneroGetAddress", + 541: "MessageType_MoneroAddress", + 542: "MessageType_MoneroGetWatchKey", + 543: "MessageType_MoneroWatchKey", + 546: "MessageType_DebugMoneroDiagRequest", + 547: "MessageType_DebugMoneroDiagAck", + 550: "MessageType_MoneroGetTxKeyRequest", + 551: "MessageType_MoneroGetTxKeyAck", + 552: "MessageType_MoneroLiveRefreshStartRequest", + 553: "MessageType_MoneroLiveRefreshStartAck", + 554: "MessageType_MoneroLiveRefreshStepRequest", + 555: "MessageType_MoneroLiveRefreshStepAck", + 556: "MessageType_MoneroLiveRefreshFinalRequest", + 557: "MessageType_MoneroLiveRefreshFinalAck", + 600: "MessageType_EosGetPublicKey", + 601: "MessageType_EosPublicKey", + 602: "MessageType_EosSignTx", + 603: "MessageType_EosTxActionRequest", + 604: "MessageType_EosTxActionAck", + 605: "MessageType_EosSignedTx", + 700: "MessageType_BinanceGetAddress", + 701: "MessageType_BinanceAddress", + 702: "MessageType_BinanceGetPublicKey", + 703: "MessageType_BinancePublicKey", + 704: "MessageType_BinanceSignTx", + 705: "MessageType_BinanceTxRequest", + 706: "MessageType_BinanceTransferMsg", + 707: "MessageType_BinanceOrderMsg", + 708: "MessageType_BinanceCancelMsg", + 709: "MessageType_BinanceSignedTx", +} + +var MessageType_value = map[string]int32{ + "MessageType_Initialize": 0, + "MessageType_Ping": 1, + "MessageType_Success": 2, + "MessageType_Failure": 3, + "MessageType_ChangePin": 4, + "MessageType_WipeDevice": 5, + "MessageType_GetEntropy": 9, + "MessageType_Entropy": 10, + "MessageType_LoadDevice": 13, + "MessageType_ResetDevice": 14, + "MessageType_Features": 17, + "MessageType_PinMatrixRequest": 18, + "MessageType_PinMatrixAck": 19, + "MessageType_Cancel": 20, + "MessageType_ClearSession": 24, + "MessageType_ApplySettings": 25, + "MessageType_ButtonRequest": 26, + "MessageType_ButtonAck": 27, + "MessageType_ApplyFlags": 28, + "MessageType_BackupDevice": 34, + "MessageType_EntropyRequest": 35, + "MessageType_EntropyAck": 36, + "MessageType_PassphraseRequest": 41, + "MessageType_PassphraseAck": 42, + "MessageType_PassphraseStateRequest": 77, + "MessageType_PassphraseStateAck": 78, + "MessageType_RecoveryDevice": 45, + "MessageType_WordRequest": 46, + "MessageType_WordAck": 47, + "MessageType_GetFeatures": 55, + "MessageType_SetU2FCounter": 63, + "MessageType_FirmwareErase": 6, + "MessageType_FirmwareUpload": 7, + "MessageType_FirmwareRequest": 8, + "MessageType_SelfTest": 32, + "MessageType_GetPublicKey": 11, + "MessageType_PublicKey": 12, + "MessageType_SignTx": 15, + "MessageType_TxRequest": 21, + "MessageType_TxAck": 22, + "MessageType_GetAddress": 29, + "MessageType_Address": 30, + "MessageType_SignMessage": 38, + "MessageType_VerifyMessage": 39, + "MessageType_MessageSignature": 40, + "MessageType_CipherKeyValue": 23, + "MessageType_CipheredKeyValue": 48, + "MessageType_SignIdentity": 53, + "MessageType_SignedIdentity": 54, + "MessageType_GetECDHSessionKey": 61, + "MessageType_ECDHSessionKey": 62, + "MessageType_CosiCommit": 71, + "MessageType_CosiCommitment": 72, + "MessageType_CosiSign": 73, + "MessageType_CosiSignature": 74, + "MessageType_DebugLinkDecision": 100, + "MessageType_DebugLinkGetState": 101, + "MessageType_DebugLinkState": 102, + "MessageType_DebugLinkStop": 103, + "MessageType_DebugLinkLog": 104, + "MessageType_DebugLinkMemoryRead": 110, + "MessageType_DebugLinkMemory": 111, + "MessageType_DebugLinkMemoryWrite": 112, + "MessageType_DebugLinkFlashErase": 113, + "MessageType_EthereumGetPublicKey": 450, + "MessageType_EthereumPublicKey": 451, + "MessageType_EthereumGetAddress": 56, + "MessageType_EthereumAddress": 57, + "MessageType_EthereumSignTx": 58, + "MessageType_EthereumTxRequest": 59, + "MessageType_EthereumTxAck": 60, + "MessageType_EthereumSignMessage": 64, + "MessageType_EthereumVerifyMessage": 65, + "MessageType_EthereumMessageSignature": 66, + "MessageType_NEMGetAddress": 67, + "MessageType_NEMAddress": 68, + "MessageType_NEMSignTx": 69, + "MessageType_NEMSignedTx": 70, + "MessageType_NEMDecryptMessage": 75, + "MessageType_NEMDecryptedMessage": 76, + "MessageType_LiskGetAddress": 114, + "MessageType_LiskAddress": 115, + "MessageType_LiskSignTx": 116, + "MessageType_LiskSignedTx": 117, + "MessageType_LiskSignMessage": 118, + "MessageType_LiskMessageSignature": 119, + "MessageType_LiskVerifyMessage": 120, + "MessageType_LiskGetPublicKey": 121, + "MessageType_LiskPublicKey": 122, + "MessageType_TezosGetAddress": 150, + "MessageType_TezosAddress": 151, + "MessageType_TezosSignTx": 152, + "MessageType_TezosSignedTx": 153, + "MessageType_TezosGetPublicKey": 154, + "MessageType_TezosPublicKey": 155, + "MessageType_StellarSignTx": 202, + "MessageType_StellarTxOpRequest": 203, + "MessageType_StellarGetAddress": 207, + "MessageType_StellarAddress": 208, + "MessageType_StellarCreateAccountOp": 210, + "MessageType_StellarPaymentOp": 211, + "MessageType_StellarPathPaymentOp": 212, + "MessageType_StellarManageOfferOp": 213, + "MessageType_StellarCreatePassiveOfferOp": 214, + "MessageType_StellarSetOptionsOp": 215, + "MessageType_StellarChangeTrustOp": 216, + "MessageType_StellarAllowTrustOp": 217, + "MessageType_StellarAccountMergeOp": 218, + "MessageType_StellarManageDataOp": 220, + "MessageType_StellarBumpSequenceOp": 221, + "MessageType_StellarSignedTx": 230, + "MessageType_TronGetAddress": 250, + "MessageType_TronAddress": 251, + "MessageType_TronSignTx": 252, + "MessageType_TronSignedTx": 253, + "MessageType_CardanoSignTx": 303, + "MessageType_CardanoTxRequest": 304, + "MessageType_CardanoGetPublicKey": 305, + "MessageType_CardanoPublicKey": 306, + "MessageType_CardanoGetAddress": 307, + "MessageType_CardanoAddress": 308, + "MessageType_CardanoTxAck": 309, + "MessageType_CardanoSignedTx": 310, + "MessageType_OntologyGetAddress": 350, + "MessageType_OntologyAddress": 351, + "MessageType_OntologyGetPublicKey": 352, + "MessageType_OntologyPublicKey": 353, + "MessageType_OntologySignTransfer": 354, + "MessageType_OntologySignedTransfer": 355, + "MessageType_OntologySignWithdrawOng": 356, + "MessageType_OntologySignedWithdrawOng": 357, + "MessageType_OntologySignOntIdRegister": 358, + "MessageType_OntologySignedOntIdRegister": 359, + "MessageType_OntologySignOntIdAddAttributes": 360, + "MessageType_OntologySignedOntIdAddAttributes": 361, + "MessageType_RippleGetAddress": 400, + "MessageType_RippleAddress": 401, + "MessageType_RippleSignTx": 402, + "MessageType_RippleSignedTx": 403, + "MessageType_MoneroTransactionInitRequest": 501, + "MessageType_MoneroTransactionInitAck": 502, + "MessageType_MoneroTransactionSetInputRequest": 503, + "MessageType_MoneroTransactionSetInputAck": 504, + "MessageType_MoneroTransactionInputsPermutationRequest": 505, + "MessageType_MoneroTransactionInputsPermutationAck": 506, + "MessageType_MoneroTransactionInputViniRequest": 507, + "MessageType_MoneroTransactionInputViniAck": 508, + "MessageType_MoneroTransactionAllInputsSetRequest": 509, + "MessageType_MoneroTransactionAllInputsSetAck": 510, + "MessageType_MoneroTransactionSetOutputRequest": 511, + "MessageType_MoneroTransactionSetOutputAck": 512, + "MessageType_MoneroTransactionAllOutSetRequest": 513, + "MessageType_MoneroTransactionAllOutSetAck": 514, + "MessageType_MoneroTransactionSignInputRequest": 515, + "MessageType_MoneroTransactionSignInputAck": 516, + "MessageType_MoneroTransactionFinalRequest": 517, + "MessageType_MoneroTransactionFinalAck": 518, + "MessageType_MoneroKeyImageExportInitRequest": 530, + "MessageType_MoneroKeyImageExportInitAck": 531, + "MessageType_MoneroKeyImageSyncStepRequest": 532, + "MessageType_MoneroKeyImageSyncStepAck": 533, + "MessageType_MoneroKeyImageSyncFinalRequest": 534, + "MessageType_MoneroKeyImageSyncFinalAck": 535, + "MessageType_MoneroGetAddress": 540, + "MessageType_MoneroAddress": 541, + "MessageType_MoneroGetWatchKey": 542, + "MessageType_MoneroWatchKey": 543, + "MessageType_DebugMoneroDiagRequest": 546, + "MessageType_DebugMoneroDiagAck": 547, + "MessageType_MoneroGetTxKeyRequest": 550, + "MessageType_MoneroGetTxKeyAck": 551, + "MessageType_MoneroLiveRefreshStartRequest": 552, + "MessageType_MoneroLiveRefreshStartAck": 553, + "MessageType_MoneroLiveRefreshStepRequest": 554, + "MessageType_MoneroLiveRefreshStepAck": 555, + "MessageType_MoneroLiveRefreshFinalRequest": 556, + "MessageType_MoneroLiveRefreshFinalAck": 557, + "MessageType_EosGetPublicKey": 600, + "MessageType_EosPublicKey": 601, + "MessageType_EosSignTx": 602, + "MessageType_EosTxActionRequest": 603, + "MessageType_EosTxActionAck": 604, + "MessageType_EosSignedTx": 605, + "MessageType_BinanceGetAddress": 700, + "MessageType_BinanceAddress": 701, + "MessageType_BinanceGetPublicKey": 702, + "MessageType_BinancePublicKey": 703, + "MessageType_BinanceSignTx": 704, + "MessageType_BinanceTxRequest": 705, + "MessageType_BinanceTransferMsg": 706, + "MessageType_BinanceOrderMsg": 707, + "MessageType_BinanceCancelMsg": 708, + "MessageType_BinanceSignedTx": 709, +} + +func (x MessageType) Enum() *MessageType { + p := new(MessageType) + *p = x + return p +} + +func (x MessageType) String() string { + return proto.EnumName(MessageType_name, int32(x)) +} + +func (x *MessageType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType") + if err != nil { + return err + } + *x = MessageType(value) + return nil +} + +func (MessageType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_4dc296cbfe5ffcd5, []int{0} +} + +var E_WireIn = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50002, + Name: "hw.trezor.messages.wire_in", + Tag: "varint,50002,opt,name=wire_in", + Filename: "messages.proto", +} + +var E_WireOut = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50003, + Name: "hw.trezor.messages.wire_out", + Tag: "varint,50003,opt,name=wire_out", + Filename: "messages.proto", +} + +var E_WireDebugIn = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50004, + Name: "hw.trezor.messages.wire_debug_in", + Tag: "varint,50004,opt,name=wire_debug_in", + Filename: "messages.proto", +} + +var E_WireDebugOut = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50005, + Name: "hw.trezor.messages.wire_debug_out", + Tag: "varint,50005,opt,name=wire_debug_out", + Filename: "messages.proto", +} + +var E_WireTiny = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50006, + Name: "hw.trezor.messages.wire_tiny", + Tag: "varint,50006,opt,name=wire_tiny", + Filename: "messages.proto", +} + +var E_WireBootloader = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50007, + Name: "hw.trezor.messages.wire_bootloader", + Tag: "varint,50007,opt,name=wire_bootloader", + Filename: "messages.proto", +} + +var E_WireNoFsm = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50008, + Name: "hw.trezor.messages.wire_no_fsm", + Tag: "varint,50008,opt,name=wire_no_fsm", + Filename: "messages.proto", +} + +func init() { + proto.RegisterEnum("hw.trezor.messages.MessageType", MessageType_name, MessageType_value) + proto.RegisterExtension(E_WireIn) + proto.RegisterExtension(E_WireOut) + proto.RegisterExtension(E_WireDebugIn) + proto.RegisterExtension(E_WireDebugOut) + proto.RegisterExtension(E_WireTiny) + proto.RegisterExtension(E_WireBootloader) + proto.RegisterExtension(E_WireNoFsm) +} + +func init() { proto.RegisterFile("messages.proto", fileDescriptor_4dc296cbfe5ffcd5) } + +var fileDescriptor_4dc296cbfe5ffcd5 = []byte{ + // 2430 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x9a, 0xd9, 0x73, 0x1c, 0xc5, + 0x1d, 0xc7, 0xb3, 0xab, 0x11, 0x88, 0xf6, 0x41, 0x23, 0xb0, 0x2d, 0xaf, 0x2f, 0xf9, 0xc0, 0x96, + 0x2f, 0xd9, 0x10, 0x0c, 0x44, 0x38, 0x60, 0x69, 0xb5, 0x12, 0x8a, 0xb5, 0x5a, 0x97, 0x76, 0xb1, + 0x1f, 0x5d, 0xa3, 0x9d, 0xd6, 0x6e, 0x97, 0x67, 0x67, 0x86, 0x9e, 0x1e, 0x49, 0xeb, 0xa7, 0x9c, + 0x3c, 0x13, 0x48, 0xc0, 0xb9, 0xa9, 0xa4, 0x2a, 0x21, 0x57, 0x85, 0x1c, 0x4e, 0x25, 0x55, 0x39, + 0x08, 0x24, 0x2f, 0xc9, 0x43, 0x52, 0x9c, 0x86, 0x40, 0xee, 0x90, 0xe4, 0x0f, 0xc8, 0xc5, 0x91, + 0xa4, 0x7a, 0xa6, 0xbb, 0xe7, 0xd8, 0xdf, 0xae, 0x36, 0x6f, 0x58, 0xf3, 0xf9, 0x7d, 0x7f, 0x47, + 0xff, 0xfa, 0x37, 0xdd, 0xb3, 0xa0, 0xcd, 0x2d, 0xe2, 0xfb, 0x66, 0x83, 0xf8, 0xe3, 0x1e, 0x73, + 0xb9, 0x3b, 0x3c, 0xdc, 0x5c, 0x1d, 0xe7, 0x8c, 0x5c, 0x76, 0xd9, 0xb8, 0x7a, 0x52, 0x18, 0x6d, + 0xb8, 0x6e, 0xc3, 0x26, 0x27, 0x42, 0x62, 0x29, 0x58, 0x3e, 0x61, 0x11, 0xbf, 0xce, 0xa8, 0xc7, + 0x5d, 0x16, 0x59, 0x1d, 0xf9, 0xfe, 0x7d, 0x68, 0x43, 0x39, 0xc2, 0x6b, 0x6d, 0x8f, 0x0c, 0x1f, + 0x40, 0x5b, 0x13, 0xff, 0xbc, 0x38, 0xe7, 0x50, 0x4e, 0x4d, 0x9b, 0x5e, 0x26, 0xf8, 0x5d, 0x85, + 0xa1, 0x87, 0xaf, 0x8e, 0xe4, 0x9e, 0xba, 0x3a, 0x92, 0x1b, 0x2e, 0x20, 0x9c, 0xa4, 0xce, 0x51, + 0xa7, 0x81, 0x73, 0x05, 0x43, 0x3c, 0x1f, 0xde, 0x85, 0x6e, 0x4e, 0x3e, 0xab, 0x06, 0xf5, 0x3a, + 0xf1, 0x7d, 0x9c, 0x2f, 0x18, 0x57, 0x80, 0xc7, 0x33, 0x26, 0xb5, 0x03, 0x46, 0xf0, 0x80, 0x7c, + 0xbc, 0x07, 0x6d, 0x49, 0x3e, 0x2e, 0x36, 0x4d, 0xa7, 0x41, 0xce, 0x51, 0x07, 0x1b, 0x52, 0x7e, + 0x34, 0x1d, 0xe0, 0x05, 0xea, 0x91, 0x69, 0xb2, 0x42, 0xeb, 0x04, 0x0f, 0xc2, 0xc4, 0x2c, 0xe1, + 0x25, 0x87, 0x33, 0xd7, 0x6b, 0xe3, 0x1b, 0xe0, 0x10, 0xd5, 0x63, 0x24, 0x63, 0xc8, 0x08, 0xcc, + 0xbb, 0xa6, 0x25, 0x5d, 0x6c, 0x92, 0x02, 0x7b, 0xd1, 0xb6, 0x24, 0xb1, 0x48, 0x7c, 0xc2, 0x25, + 0xb2, 0x59, 0x22, 0xbb, 0xd1, 0x2d, 0xa9, 0x3c, 0x89, 0xc9, 0x03, 0x46, 0x7c, 0x7c, 0x93, 0x74, + 0x72, 0x10, 0xed, 0xcc, 0x94, 0xb0, 0x6c, 0x72, 0x46, 0xd7, 0x16, 0xc9, 0x83, 0x01, 0xf1, 0x39, + 0x1e, 0x96, 0xdc, 0x11, 0x34, 0x02, 0x72, 0x93, 0xf5, 0x4b, 0xf8, 0xe6, 0xc2, 0x46, 0xb5, 0x24, + 0x4f, 0x47, 0x81, 0x0f, 0xa7, 0x8a, 0x67, 0x3a, 0x75, 0x62, 0xe3, 0x5b, 0x12, 0x0b, 0xb7, 0x2f, + 0xad, 0x56, 0xb4, 0x89, 0xc9, 0xaa, 0xc4, 0xf7, 0xa9, 0xeb, 0xe0, 0x11, 0x19, 0xf9, 0x7e, 0xb4, + 0x3d, 0xc9, 0x4c, 0x7a, 0x9e, 0xdd, 0xae, 0x12, 0xce, 0xa9, 0xd3, 0xf0, 0xf1, 0x76, 0x18, 0x9a, + 0x0a, 0x38, 0x77, 0x1d, 0x15, 0x7b, 0x41, 0xc6, 0x7e, 0x28, 0xbd, 0x98, 0x11, 0x24, 0x02, 0xdf, + 0xd1, 0x11, 0xf8, 0xd6, 0x0e, 0x97, 0x33, 0xb6, 0xd9, 0xf0, 0xf1, 0x4e, 0xe9, 0x2f, 0x13, 0xf8, + 0x94, 0x59, 0xbf, 0x14, 0x78, 0xb2, 0xe4, 0xfb, 0x24, 0x73, 0x00, 0x15, 0x80, 0x65, 0x55, 0x41, + 0xed, 0x87, 0x57, 0x57, 0x52, 0x22, 0xaa, 0x03, 0x52, 0xe7, 0x10, 0xda, 0x95, 0x2a, 0xb9, 0xe9, + 0xfb, 0x5e, 0x93, 0x99, 0x3e, 0x51, 0x52, 0x87, 0xa5, 0xd4, 0xd1, 0x74, 0x11, 0x62, 0x50, 0xa8, + 0x1d, 0xc9, 0xe4, 0x78, 0x0c, 0xed, 0x83, 0xe1, 0x2a, 0x37, 0xb9, 0x96, 0x2e, 0x4b, 0xe9, 0x93, + 0x68, 0x77, 0x0f, 0x5a, 0xe8, 0x2f, 0x64, 0xf4, 0x33, 0xd9, 0x2f, 0x92, 0xba, 0xbb, 0x42, 0x58, + 0x5b, 0xd6, 0xe8, 0x38, 0xdc, 0xb9, 0x17, 0x5c, 0x66, 0x29, 0xd7, 0xe3, 0xf0, 0x0e, 0x15, 0x88, + 0xf0, 0x77, 0x02, 0x56, 0x98, 0x25, 0x5c, 0xf7, 0xf6, 0x5d, 0x70, 0x73, 0x54, 0x09, 0x7f, 0xe0, + 0xf6, 0x99, 0xa2, 0x1b, 0x38, 0x9c, 0x30, 0x7c, 0x9f, 0xae, 0x72, 0x0a, 0x9a, 0xa1, 0xac, 0xb5, + 0x6a, 0x32, 0x52, 0x12, 0x49, 0xe2, 0xeb, 0xa2, 0x9e, 0xfd, 0x9e, 0x00, 0xc7, 0xd2, 0x89, 0x29, + 0xf0, 0x01, 0xcf, 0x76, 0x4d, 0x0b, 0x5f, 0x9f, 0x20, 0x0f, 0xa3, 0x1d, 0x10, 0xa9, 0x12, 0x1c, + 0x2a, 0x0c, 0x5d, 0x51, 0xe8, 0xbe, 0xf4, 0xf6, 0xac, 0x12, 0x7b, 0xb9, 0x26, 0x98, 0xd1, 0x84, + 0x5c, 0xa6, 0xe7, 0x66, 0x09, 0x3f, 0x17, 0x2c, 0xd9, 0xb4, 0x7e, 0x96, 0xb4, 0xf1, 0x06, 0x99, + 0x45, 0x66, 0x5e, 0xc5, 0xc0, 0x46, 0x59, 0xcd, 0x9d, 0xe9, 0x3d, 0x59, 0xa5, 0x0d, 0xa7, 0xb6, + 0x86, 0x6f, 0x84, 0xcd, 0x6b, 0x7a, 0xfb, 0x6f, 0x91, 0xe6, 0x3b, 0xd0, 0x4d, 0x69, 0x40, 0x2c, + 0xc5, 0xd6, 0xae, 0x93, 0x6e, 0xd2, 0xb2, 0x98, 0x98, 0xb6, 0xbb, 0xe0, 0x49, 0xa7, 0x1e, 0xef, + 0x96, 0xea, 0x99, 0xb5, 0x14, 0xc1, 0xc9, 0x7f, 0xe3, 0x83, 0xf0, 0x5a, 0x9e, 0x27, 0x8c, 0x2e, + 0xb7, 0x15, 0x74, 0x48, 0x42, 0x99, 0x61, 0x26, 0xff, 0x5b, 0xc8, 0x85, 0x9d, 0x81, 0xc7, 0xa4, + 0xbf, 0x4c, 0x8f, 0x16, 0xa9, 0xd7, 0x24, 0xec, 0x2c, 0x69, 0x9f, 0x37, 0xed, 0x80, 0xe0, 0x6d, + 0xb0, 0x5a, 0x44, 0x11, 0x4b, 0x73, 0x27, 0xa5, 0x5a, 0x66, 0x7d, 0x84, 0xbb, 0x39, 0x8b, 0x38, + 0x9c, 0xf2, 0x36, 0x3e, 0x05, 0xcf, 0x04, 0xc1, 0x10, 0x4b, 0x53, 0x77, 0xea, 0x41, 0xb5, 0x2b, + 0xfb, 0xca, 0x28, 0x4e, 0xdf, 0x2f, 0x07, 0xa3, 0x58, 0xcd, 0xf7, 0x76, 0x19, 0x31, 0x69, 0xea, + 0x5e, 0x78, 0xc4, 0x14, 0x5d, 0x9f, 0x16, 0xdd, 0x56, 0x8b, 0x72, 0x3c, 0x0b, 0xeb, 0xc4, 0x44, + 0x8b, 0x38, 0x1c, 0xdf, 0x2f, 0x75, 0x32, 0xef, 0x10, 0x41, 0x89, 0x04, 0xf0, 0x1c, 0xbc, 0x36, + 0xea, 0x79, 0x54, 0xf3, 0xf7, 0x49, 0x91, 0x13, 0xe9, 0xdc, 0xa6, 0xc9, 0x52, 0xd0, 0x98, 0xa7, + 0xce, 0xa5, 0x69, 0x52, 0xa7, 0xe1, 0xdc, 0xb7, 0x0a, 0x1b, 0x9f, 0x48, 0x0e, 0x92, 0xa3, 0x5d, + 0x0c, 0x66, 0x09, 0x0f, 0x87, 0x0f, 0x26, 0x85, 0x21, 0x65, 0x90, 0x4d, 0x44, 0xc3, 0x11, 0xb9, + 0x5c, 0x30, 0x9e, 0x04, 0x02, 0x4d, 0x50, 0xae, 0x87, 0x1b, 0x05, 0xe3, 0x09, 0x60, 0x39, 0x35, + 0x34, 0xef, 0x36, 0x70, 0x53, 0x0a, 0x1d, 0x46, 0x7b, 0x40, 0xa6, 0x4c, 0x5a, 0x2e, 0x6b, 0x2f, + 0x12, 0xd3, 0xc2, 0x8e, 0x94, 0xbb, 0x35, 0x3d, 0x0c, 0x32, 0x28, 0x76, 0xa5, 0xe2, 0x11, 0x34, + 0xda, 0x03, 0xbb, 0xc0, 0x28, 0x27, 0xd8, 0x93, 0x92, 0xdd, 0xbc, 0xcf, 0xd8, 0xa6, 0xdf, 0x8c, + 0x06, 0xd7, 0x83, 0x12, 0x3d, 0x9a, 0x96, 0x2d, 0x71, 0xd1, 0xc2, 0x41, 0x2b, 0x35, 0x43, 0x9e, + 0x19, 0x90, 0xeb, 0x38, 0x96, 0xae, 0xb8, 0x82, 0x63, 0xf2, 0x59, 0x75, 0x3c, 0x1a, 0x4b, 0xbf, + 0x16, 0x12, 0xb2, 0x6a, 0x6b, 0xdf, 0x2d, 0x35, 0x33, 0xe9, 0x2b, 0x52, 0x61, 0xef, 0x81, 0x77, + 0xa4, 0xc2, 0xe4, 0x98, 0x9a, 0x80, 0xdf, 0x88, 0x8a, 0x8a, 0xc7, 0xd5, 0x3d, 0x52, 0x2e, 0xb3, + 0xd0, 0x31, 0x28, 0xc6, 0xd6, 0x69, 0xa9, 0x96, 0x29, 0x63, 0xd2, 0xa7, 0x1a, 0x2c, 0x67, 0x24, + 0x7a, 0x14, 0xed, 0x85, 0xd0, 0xf4, 0x14, 0x9a, 0x94, 0xf0, 0x38, 0x3a, 0x00, 0xc1, 0x1d, 0xd3, + 0x68, 0x0a, 0x0e, 0x76, 0xa1, 0x54, 0x4e, 0xd4, 0xb1, 0x08, 0xcf, 0xd8, 0x85, 0x52, 0x59, 0x11, + 0xd3, 0xf0, 0x91, 0x75, 0xa1, 0x54, 0x96, 0xd5, 0x2b, 0xc1, 0x6f, 0x4c, 0x09, 0x10, 0xab, 0xb6, + 0x86, 0x67, 0xe0, 0x01, 0xb4, 0x50, 0x2a, 0x4f, 0x93, 0x3a, 0x6b, 0x7b, 0x5c, 0xe5, 0x78, 0x16, + 0xae, 0x5d, 0x0c, 0x12, 0x4b, 0xa1, 0xf3, 0xf0, 0xd2, 0xce, 0x53, 0xff, 0x52, 0x22, 0x3f, 0x06, + 0x07, 0x27, 0x28, 0x85, 0xf8, 0x5d, 0xce, 0xc3, 0xd4, 0xbf, 0x24, 0x33, 0xe4, 0xf0, 0xe9, 0x4c, + 0x11, 0x61, 0x8a, 0x81, 0x54, 0xc9, 0x34, 0xa4, 0x62, 0x54, 0xd4, 0x2b, 0x52, 0x2a, 0xb3, 0x1f, + 0x05, 0xd6, 0xb1, 0x80, 0xab, 0x70, 0xd5, 0x04, 0x9b, 0xee, 0x8c, 0x35, 0xf8, 0x8d, 0x22, 0x4b, + 0x11, 0xef, 0xaf, 0x36, 0x3c, 0x50, 0x05, 0x17, 0x43, 0x97, 0xf5, 0xc9, 0x3d, 0x95, 0x48, 0x8d, + 0x5c, 0x76, 0xfd, 0x44, 0x61, 0x1f, 0xcb, 0x69, 0xb1, 0x91, 0x0e, 0x4e, 0x41, 0x8f, 0xe7, 0xf4, + 0x3b, 0x6c, 0x5b, 0x07, 0x24, 0x8b, 0x7b, 0x25, 0xa7, 0x5f, 0x16, 0xdb, 0x41, 0x26, 0x2c, 0xef, + 0x27, 0x72, 0x7a, 0x34, 0xec, 0x82, 0xc2, 0x8a, 0xe3, 0xff, 0x64, 0x4e, 0x8f, 0x86, 0x42, 0x07, + 0x19, 0x63, 0x9f, 0xca, 0xe9, 0xfe, 0x49, 0x9f, 0xe2, 0x38, 0xb1, 0x6d, 0x93, 0xc9, 0xe0, 0x7e, + 0x9e, 0xd3, 0x0d, 0xb9, 0x1b, 0xa0, 0x6a, 0x6b, 0x15, 0x4f, 0xcd, 0x86, 0x5f, 0x74, 0x89, 0x50, + 0xa2, 0x89, 0xd2, 0xfd, 0xb2, 0x4b, 0x84, 0x92, 0x54, 0xd8, 0xaf, 0x94, 0xe0, 0xf1, 0xf4, 0x91, + 0x5a, 0x62, 0x45, 0x46, 0xc2, 0x23, 0x72, 0x5d, 0x1c, 0x38, 0x2b, 0x1e, 0x7e, 0x2e, 0xa7, 0xa7, + 0xd8, 0x4e, 0x00, 0x3f, 0x67, 0xb6, 0xc5, 0x4b, 0xb7, 0xe2, 0xe1, 0xe7, 0x73, 0x7a, 0xea, 0x8c, + 0x82, 0x20, 0x6f, 0xc6, 0xf0, 0x0b, 0xbd, 0xe1, 0xb2, 0xe9, 0x98, 0x0d, 0x52, 0x59, 0x5e, 0x26, + 0xac, 0xe2, 0xe1, 0x17, 0x15, 0x7c, 0x3b, 0x3a, 0xd4, 0x35, 0x62, 0x71, 0xc6, 0xa7, 0x2b, 0xda, + 0xe6, 0xa5, 0x9c, 0xde, 0x11, 0x7b, 0xa0, 0x75, 0x20, 0xbc, 0xe2, 0x71, 0xea, 0x3a, 0x7e, 0xc5, + 0xc3, 0x2f, 0xf7, 0x0e, 0x26, 0xba, 0x45, 0xd7, 0x58, 0xe0, 0x8b, 0xc8, 0xaf, 0xf5, 0x16, 0x9e, + 0xb4, 0x6d, 0x77, 0x55, 0xb1, 0xaf, 0x28, 0xf6, 0x58, 0x7a, 0x10, 0x2b, 0x36, 0x2a, 0x72, 0x99, + 0xb0, 0x06, 0xa9, 0x78, 0xf8, 0xd5, 0xde, 0xca, 0x51, 0x4d, 0xa6, 0x4d, 0x6e, 0x56, 0x3c, 0xfc, + 0x5a, 0x6f, 0xe5, 0xa9, 0xa0, 0xe5, 0x55, 0x45, 0x03, 0x39, 0x75, 0xa1, 0xfc, 0x7a, 0x4e, 0xef, + 0xe4, 0x1d, 0x5d, 0x9a, 0x32, 0xdc, 0x0d, 0x6f, 0xe4, 0xf4, 0xb4, 0x49, 0xf7, 0x38, 0x73, 0x9d, + 0x44, 0xa3, 0xbd, 0x99, 0xd3, 0x83, 0x6b, 0x5b, 0x16, 0x53, 0xcc, 0x5b, 0x39, 0x7d, 0x48, 0xde, + 0x9a, 0x65, 0xe4, 0x26, 0x78, 0xbb, 0xdb, 0x56, 0x97, 0x48, 0x18, 0xd2, 0x3b, 0x5d, 0xf6, 0x53, + 0xd1, 0x64, 0x96, 0xe9, 0xb8, 0x52, 0xea, 0x1b, 0x79, 0xb8, 0x49, 0x25, 0x15, 0xbf, 0x69, 0x9f, + 0xca, 0xeb, 0x0f, 0x03, 0x7b, 0x00, 0x30, 0xb5, 0xe3, 0xbf, 0xd9, 0x5b, 0x34, 0x06, 0xbf, 0x95, + 0x87, 0xb7, 0x68, 0x2c, 0xaa, 0xaa, 0xf2, 0xed, 0x3c, 0xbc, 0x45, 0x25, 0xa9, 0xb0, 0xef, 0xe4, + 0xf5, 0x3b, 0x76, 0x04, 0x4c, 0x47, 0x9c, 0x07, 0xae, 0xe6, 0xe1, 0x45, 0x4d, 0x54, 0x26, 0xac, + 0xe0, 0x77, 0x95, 0x58, 0x66, 0xd6, 0x54, 0x1c, 0xee, 0xda, 0x6e, 0xa3, 0x9d, 0x08, 0xef, 0x37, + 0x5d, 0x24, 0x15, 0xaa, 0xb8, 0xdf, 0xe6, 0xf5, 0x15, 0x7e, 0xb4, 0x8b, 0x64, 0x5c, 0x9d, 0xdf, + 0xe5, 0xe1, 0x73, 0x9a, 0x82, 0x63, 0xf2, 0xf7, 0xeb, 0xc8, 0x86, 0x8b, 0xcd, 0x4c, 0xc7, 0x5f, + 0x26, 0x0c, 0xff, 0x41, 0xc9, 0x66, 0xc6, 0x58, 0x12, 0x26, 0x96, 0xc6, 0xff, 0xa8, 0xb4, 0xc7, + 0xd1, 0xfe, 0x6e, 0xf8, 0x05, 0xca, 0x9b, 0x16, 0x33, 0x57, 0x2b, 0x4e, 0x03, 0xff, 0x49, 0xc9, + 0x9f, 0x44, 0xb7, 0x76, 0x97, 0x4f, 0x5a, 0xfc, 0x39, 0xaf, 0x3f, 0x3e, 0x74, 0xb5, 0xa8, 0x38, + 0x7c, 0xce, 0x5a, 0x24, 0x0d, 0xea, 0x8b, 0xbb, 0xfc, 0x1b, 0x79, 0x78, 0xae, 0xa5, 0x7d, 0xa4, + 0x6d, 0xfe, 0xa2, 0xbc, 0x9c, 0x42, 0x47, 0x7a, 0x7a, 0x99, 0xb4, 0xac, 0x49, 0xce, 0x19, 0x5d, + 0x0a, 0x38, 0xf1, 0xf1, 0x5f, 0x95, 0xab, 0xbb, 0xd0, 0xb1, 0x75, 0x5c, 0xa5, 0x0d, 0xff, 0x96, + 0xd7, 0xa7, 0x85, 0xd4, 0x26, 0x58, 0xa4, 0x9e, 0x67, 0x93, 0x44, 0xef, 0x3c, 0x3c, 0x00, 0xbf, + 0x6f, 0x23, 0x50, 0x51, 0x1f, 0x1d, 0x80, 0x3b, 0x3b, 0xa2, 0xe4, 0x6e, 0x7e, 0x64, 0x00, 0xde, + 0x25, 0x31, 0x14, 0x36, 0xf6, 0xa3, 0x0a, 0x7b, 0x37, 0x1a, 0x4b, 0xdd, 0x9f, 0x5d, 0x87, 0x30, + 0x37, 0x5c, 0x79, 0xb3, 0x2e, 0x66, 0xfc, 0x9c, 0x43, 0xb9, 0x1a, 0x00, 0x7f, 0x1f, 0xd0, 0x17, + 0xbb, 0x03, 0xeb, 0x1a, 0x89, 0x6d, 0xf6, 0x0f, 0x65, 0x90, 0xa9, 0x5c, 0x87, 0x41, 0x95, 0xf0, + 0x39, 0xc7, 0x0b, 0xb4, 0xa7, 0x7f, 0x2a, 0xc3, 0xf5, 0xc2, 0x53, 0x86, 0xc2, 0xdb, 0xbf, 0x94, + 0xd1, 0x19, 0x74, 0x6a, 0x9d, 0xf0, 0xbc, 0x80, 0xfb, 0xe7, 0x08, 0x6b, 0x05, 0xdc, 0x14, 0x7f, + 0x50, 0x6e, 0xff, 0xad, 0x14, 0x4e, 0xa3, 0xdb, 0xfe, 0x3f, 0x05, 0xe1, 0xff, 0x4d, 0x65, 0x7d, + 0x37, 0x3a, 0xbe, 0xbe, 0xf5, 0x79, 0xea, 0x50, 0xe5, 0xf7, 0x2d, 0x65, 0x79, 0x07, 0x3a, 0xdc, + 0x9f, 0xa5, 0xf0, 0xf7, 0xb6, 0xb2, 0xba, 0x07, 0x9d, 0xec, 0x69, 0x35, 0x69, 0xdb, 0x51, 0xc0, + 0x55, 0xa2, 0x2b, 0xfc, 0x4e, 0xbf, 0x4b, 0x93, 0x34, 0x16, 0x5e, 0xff, 0xd3, 0x6f, 0x96, 0xe2, + 0x98, 0x10, 0xf0, 0xc4, 0xa2, 0xfe, 0xb7, 0xdf, 0x2c, 0xb5, 0xa5, 0xf0, 0xf7, 0x7e, 0xa3, 0x4f, + 0x7f, 0x93, 0xb6, 0x5d, 0x09, 0x78, 0x22, 0xc5, 0x0f, 0x18, 0x7d, 0xfa, 0xd3, 0x96, 0xc2, 0xdf, + 0x07, 0xfb, 0xf5, 0x17, 0x7e, 0xf4, 0x49, 0x36, 0xed, 0x87, 0xfa, 0xf5, 0xa7, 0x2d, 0x85, 0xbf, + 0x0f, 0xf7, 0x6b, 0x35, 0x43, 0x1d, 0xd3, 0x56, 0xbe, 0x3e, 0x62, 0xc0, 0x03, 0x13, 0xb6, 0x12, + 0x7e, 0x1e, 0x52, 0x16, 0x77, 0xa2, 0xa3, 0x9d, 0x16, 0x67, 0x49, 0x7b, 0xae, 0x65, 0x36, 0x48, + 0x69, 0xcd, 0x73, 0x19, 0x4f, 0x6e, 0xfa, 0x47, 0x94, 0x5d, 0x66, 0xd0, 0x76, 0xb3, 0x13, 0xbe, + 0x1e, 0xed, 0x99, 0x93, 0xb2, 0xa9, 0xb6, 0x9d, 0x7a, 0x95, 0x13, 0x7d, 0x5a, 0xff, 0x58, 0xcf, + 0x9c, 0xb2, 0x56, 0xc2, 0xcf, 0xc7, 0x0d, 0x78, 0xa0, 0x77, 0x5a, 0xa4, 0x8a, 0xf7, 0x98, 0x32, + 0xbb, 0x0d, 0x1d, 0xec, 0xc3, 0x4c, 0x78, 0x7a, 0xdc, 0x80, 0x47, 0x79, 0x64, 0x92, 0x18, 0xe5, + 0x9f, 0x36, 0xe0, 0x51, 0x1e, 0x81, 0x8a, 0xfa, 0x8c, 0x01, 0x9f, 0x7a, 0xb4, 0xdc, 0x05, 0x93, + 0xd7, 0x9b, 0xe2, 0xbd, 0xfe, 0x59, 0x03, 0x9e, 0xe7, 0x11, 0xa9, 0xb1, 0xcf, 0x19, 0xf0, 0xc5, + 0x24, 0xfc, 0x50, 0x14, 0xb1, 0xd3, 0xd4, 0x6c, 0xa8, 0x0a, 0x7c, 0xde, 0x80, 0xef, 0x50, 0x19, + 0x5c, 0x64, 0xfe, 0x05, 0xa5, 0x9c, 0x39, 0x2d, 0xeb, 0x50, 0x6b, 0x6b, 0x67, 0x89, 0xfe, 0xa9, + 0xe3, 0x8b, 0x06, 0x7c, 0x60, 0x49, 0xd3, 0x42, 0xf7, 0x4b, 0x3d, 0x7b, 0x64, 0x9e, 0xae, 0x90, + 0x45, 0xb2, 0xcc, 0x88, 0xdf, 0xac, 0x72, 0x93, 0xe9, 0x6e, 0x7c, 0xd2, 0x80, 0x8f, 0x16, 0xb0, + 0x95, 0xf0, 0xf3, 0x65, 0xa3, 0xd7, 0xab, 0x24, 0x65, 0x11, 0xb7, 0xe2, 0x57, 0x94, 0x1b, 0xf0, + 0x4d, 0x97, 0x31, 0x12, 0x5e, 0xbe, 0xda, 0x6f, 0x36, 0xa9, 0x46, 0xfc, 0x5a, 0xbf, 0xd9, 0xe8, + 0x3e, 0xfc, 0xba, 0x01, 0x7f, 0x0a, 0x28, 0x65, 0x6e, 0xdc, 0xd7, 0x0c, 0xf8, 0x7e, 0x50, 0x4a, + 0xde, 0xb7, 0x5f, 0x31, 0xf4, 0x67, 0x96, 0x2d, 0x19, 0x48, 0x9e, 0x26, 0x5e, 0xed, 0xd2, 0x27, + 0x25, 0xd7, 0x17, 0x07, 0xe9, 0xe4, 0xbb, 0xf3, 0xd7, 0x06, 0x7c, 0xff, 0x49, 0xa0, 0x22, 0x81, + 0xd7, 0x0c, 0xf8, 0xfe, 0x53, 0x4a, 0x7c, 0x58, 0x78, 0xbd, 0xcb, 0xee, 0x98, 0xa2, 0x8e, 0xe9, + 0xd4, 0x93, 0x07, 0xa7, 0x1f, 0x0c, 0xc2, 0xbb, 0x43, 0x92, 0x0a, 0xfb, 0xe1, 0x20, 0x7c, 0x73, + 0x89, 0x05, 0xe3, 0xa2, 0xfc, 0x68, 0x10, 0xbe, 0xb9, 0x48, 0x36, 0x06, 0x7f, 0x3c, 0x08, 0xdf, + 0xae, 0x24, 0x28, 0x2b, 0xf8, 0x74, 0x6f, 0xb9, 0xf8, 0x76, 0xf5, 0x93, 0x41, 0xf8, 0xaa, 0xa1, + 0x40, 0x79, 0x18, 0x2f, 0xfb, 0x0d, 0xfc, 0xcc, 0x20, 0x7c, 0xd5, 0x90, 0x68, 0x85, 0x59, 0x11, + 0xf7, 0x6c, 0x6f, 0xdf, 0xd1, 0x8f, 0xb4, 0x02, 0xfc, 0x69, 0x6f, 0x41, 0xbd, 0x30, 0x3f, 0x93, + 0x31, 0x4e, 0x9c, 0x46, 0xd7, 0xaf, 0x52, 0x46, 0x2e, 0x52, 0x67, 0x78, 0xef, 0x78, 0xf4, 0x4b, + 0xff, 0xb8, 0xfa, 0xa5, 0x7f, 0xbc, 0xe4, 0x04, 0xad, 0xf0, 0xe7, 0x12, 0xf9, 0x95, 0x60, 0xe4, + 0xb9, 0x87, 0x06, 0x46, 0x73, 0x63, 0x43, 0x8b, 0xd7, 0x09, 0x9b, 0x39, 0x67, 0xe2, 0x5e, 0x34, + 0x14, 0x5a, 0xbb, 0x01, 0xef, 0xc7, 0xfc, 0x79, 0x69, 0x1e, 0xba, 0xac, 0x04, 0x7c, 0x62, 0x16, + 0x6d, 0x0a, 0xed, 0x2d, 0x31, 0xad, 0xfa, 0x8c, 0xe1, 0x05, 0x29, 0xb2, 0x41, 0x58, 0x86, 0x63, + 0x6e, 0xce, 0x99, 0x98, 0x43, 0x9b, 0x13, 0x42, 0x7d, 0x86, 0xf3, 0xa2, 0x54, 0xda, 0xa8, 0x95, + 0x44, 0x4c, 0x67, 0xd0, 0x0d, 0xa1, 0x14, 0xa7, 0x4e, 0xbb, 0x1f, 0x95, 0x97, 0xa4, 0x4a, 0x58, + 0x89, 0x1a, 0x75, 0xda, 0x13, 0xf3, 0xe8, 0xc6, 0x50, 0x61, 0xc9, 0x75, 0xb9, 0xed, 0x9a, 0x16, + 0x61, 0xfd, 0xe8, 0xbc, 0x2c, 0x75, 0xc2, 0x44, 0xa6, 0xb4, 0xe9, 0x44, 0x11, 0x85, 0x99, 0x5e, + 0x74, 0xdc, 0x8b, 0xcb, 0x7e, 0xab, 0x1f, 0xa5, 0x6b, 0x52, 0x29, 0xcc, 0x63, 0xc1, 0x9d, 0xf1, + 0x5b, 0x53, 0x77, 0xa0, 0xfd, 0x75, 0xb7, 0x35, 0xee, 0x9b, 0xdc, 0xf5, 0x9b, 0xd4, 0x36, 0x97, + 0x7c, 0xf5, 0xff, 0x79, 0xd8, 0x74, 0x49, 0x4b, 0x4d, 0x6d, 0xaa, 0x85, 0x7f, 0x94, 0x9d, 0xf3, + 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x69, 0x67, 0x5d, 0x1f, 0x22, 0x00, 0x00, +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto new file mode 100644 index 000000000..3e0482e34 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/messages.proto @@ -0,0 +1,264 @@ +// This file originates from the SatoshiLabs Trezor `common` repository at: +// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto +// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. + +syntax = "proto2"; +package hw.trezor.messages; + +/** + * Messages for TREZOR communication + */ + +// Sugar for easier handling in Java +option java_package = "com.satoshilabs.trezor.lib.protobuf"; +option java_outer_classname = "TrezorMessage"; + +import "google/protobuf/descriptor.proto"; + +/** + * Options for specifying message direction and type of wire (normal/debug) + */ +extend google.protobuf.EnumValueOptions { + optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR + optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC + optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR + optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC + optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode + optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader + optional bool wire_no_fsm = 50008; // message is not handled by TREZOR unless the USB stack is in tiny mode +} + +/** + * Mapping between TREZOR wire identifier (uint) and a protobuf message + */ +enum MessageType { + + // Management + MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = true]; + MessageType_Ping = 1 [(wire_in) = true]; + MessageType_Success = 2 [(wire_out) = true]; + MessageType_Failure = 3 [(wire_out) = true]; + MessageType_ChangePin = 4 [(wire_in) = true]; + MessageType_WipeDevice = 5 [(wire_in) = true]; + MessageType_GetEntropy = 9 [(wire_in) = true]; + MessageType_Entropy = 10 [(wire_out) = true]; + MessageType_LoadDevice = 13 [(wire_in) = true]; + MessageType_ResetDevice = 14 [(wire_in) = true]; + MessageType_Features = 17 [(wire_out) = true]; + MessageType_PinMatrixRequest = 18 [(wire_out) = true]; + MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; + MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true]; + MessageType_ClearSession = 24 [(wire_in) = true]; + MessageType_ApplySettings = 25 [(wire_in) = true]; + MessageType_ButtonRequest = 26 [(wire_out) = true]; + MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; + MessageType_ApplyFlags = 28 [(wire_in) = true]; + MessageType_BackupDevice = 34 [(wire_in) = true]; + MessageType_EntropyRequest = 35 [(wire_out) = true]; + MessageType_EntropyAck = 36 [(wire_in) = true]; + MessageType_PassphraseRequest = 41 [(wire_out) = true]; + MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; + MessageType_PassphraseStateRequest = 77 [(wire_out) = true]; + MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; + MessageType_RecoveryDevice = 45 [(wire_in) = true]; + MessageType_WordRequest = 46 [(wire_out) = true]; + MessageType_WordAck = 47 [(wire_in) = true]; + MessageType_GetFeatures = 55 [(wire_in) = true]; + MessageType_SetU2FCounter = 63 [(wire_in) = true]; + + // Bootloader + MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true]; + MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true]; + MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true]; + MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true]; + + // Bitcoin + MessageType_GetPublicKey = 11 [(wire_in) = true]; + MessageType_PublicKey = 12 [(wire_out) = true]; + MessageType_SignTx = 15 [(wire_in) = true]; + MessageType_TxRequest = 21 [(wire_out) = true]; + MessageType_TxAck = 22 [(wire_in) = true]; + MessageType_GetAddress = 29 [(wire_in) = true]; + MessageType_Address = 30 [(wire_out) = true]; + MessageType_SignMessage = 38 [(wire_in) = true]; + MessageType_VerifyMessage = 39 [(wire_in) = true]; + MessageType_MessageSignature = 40 [(wire_out) = true]; + + // Crypto + MessageType_CipherKeyValue = 23 [(wire_in) = true]; + MessageType_CipheredKeyValue = 48 [(wire_out) = true]; + MessageType_SignIdentity = 53 [(wire_in) = true]; + MessageType_SignedIdentity = 54 [(wire_out) = true]; + MessageType_GetECDHSessionKey = 61 [(wire_in) = true]; + MessageType_ECDHSessionKey = 62 [(wire_out) = true]; + MessageType_CosiCommit = 71 [(wire_in) = true]; + MessageType_CosiCommitment = 72 [(wire_out) = true]; + MessageType_CosiSign = 73 [(wire_in) = true]; + MessageType_CosiSignature = 74 [(wire_out) = true]; + + // Debug + MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; + MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = true]; + MessageType_DebugLinkState = 102 [(wire_debug_out) = true]; + MessageType_DebugLinkStop = 103 [(wire_debug_in) = true]; + MessageType_DebugLinkLog = 104 [(wire_debug_out) = true]; + MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true]; + MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true]; + MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true]; + MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true]; + + // Ethereum + MessageType_EthereumGetPublicKey = 450 [(wire_in) = true]; + MessageType_EthereumPublicKey = 451 [(wire_out) = true]; + MessageType_EthereumGetAddress = 56 [(wire_in) = true]; + MessageType_EthereumAddress = 57 [(wire_out) = true]; + MessageType_EthereumSignTx = 58 [(wire_in) = true]; + MessageType_EthereumTxRequest = 59 [(wire_out) = true]; + MessageType_EthereumTxAck = 60 [(wire_in) = true]; + MessageType_EthereumSignMessage = 64 [(wire_in) = true]; + MessageType_EthereumVerifyMessage = 65 [(wire_in) = true]; + MessageType_EthereumMessageSignature = 66 [(wire_out) = true]; + + // NEM + MessageType_NEMGetAddress = 67 [(wire_in) = true]; + MessageType_NEMAddress = 68 [(wire_out) = true]; + MessageType_NEMSignTx = 69 [(wire_in) = true]; + MessageType_NEMSignedTx = 70 [(wire_out) = true]; + MessageType_NEMDecryptMessage = 75 [(wire_in) = true]; + MessageType_NEMDecryptedMessage = 76 [(wire_out) = true]; + + // Lisk + MessageType_LiskGetAddress = 114 [(wire_in) = true]; + MessageType_LiskAddress = 115 [(wire_out) = true]; + MessageType_LiskSignTx = 116 [(wire_in) = true]; + MessageType_LiskSignedTx = 117 [(wire_out) = true]; + MessageType_LiskSignMessage = 118 [(wire_in) = true]; + MessageType_LiskMessageSignature = 119 [(wire_out) = true]; + MessageType_LiskVerifyMessage = 120 [(wire_in) = true]; + MessageType_LiskGetPublicKey = 121 [(wire_in) = true]; + MessageType_LiskPublicKey = 122 [(wire_out) = true]; + + // Tezos + MessageType_TezosGetAddress = 150 [(wire_in) = true]; + MessageType_TezosAddress = 151 [(wire_out) = true]; + MessageType_TezosSignTx = 152 [(wire_in) = true]; + MessageType_TezosSignedTx = 153 [(wire_out) = true]; + MessageType_TezosGetPublicKey = 154 [(wire_in) = true]; + MessageType_TezosPublicKey = 155 [(wire_out) = true]; + + // Stellar + MessageType_StellarSignTx = 202 [(wire_in) = true]; + MessageType_StellarTxOpRequest = 203 [(wire_out) = true]; + MessageType_StellarGetAddress = 207 [(wire_in) = true]; + MessageType_StellarAddress = 208 [(wire_out) = true]; + MessageType_StellarCreateAccountOp = 210 [(wire_in) = true]; + MessageType_StellarPaymentOp = 211 [(wire_in) = true]; + MessageType_StellarPathPaymentOp = 212 [(wire_in) = true]; + MessageType_StellarManageOfferOp = 213 [(wire_in) = true]; + MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true]; + MessageType_StellarSetOptionsOp = 215 [(wire_in) = true]; + MessageType_StellarChangeTrustOp = 216 [(wire_in) = true]; + MessageType_StellarAllowTrustOp = 217 [(wire_in) = true]; + MessageType_StellarAccountMergeOp = 218 [(wire_in) = true]; + // omitted: StellarInflationOp is not a supported operation, would be 219 + MessageType_StellarManageDataOp = 220 [(wire_in) = true]; + MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true]; + MessageType_StellarSignedTx = 230 [(wire_out) = true]; + + // TRON + MessageType_TronGetAddress = 250 [(wire_in) = true]; + MessageType_TronAddress = 251 [(wire_out) = true]; + MessageType_TronSignTx = 252 [(wire_in) = true]; + MessageType_TronSignedTx = 253 [(wire_out) = true]; + + // Cardano + // dropped Sign/VerifyMessage ids 300-302 + MessageType_CardanoSignTx = 303 [(wire_in) = true]; + MessageType_CardanoTxRequest = 304 [(wire_out) = true]; + MessageType_CardanoGetPublicKey = 305 [(wire_in) = true]; + MessageType_CardanoPublicKey = 306 [(wire_out) = true]; + MessageType_CardanoGetAddress = 307 [(wire_in) = true]; + MessageType_CardanoAddress = 308 [(wire_out) = true]; + MessageType_CardanoTxAck = 309 [(wire_in) = true]; + MessageType_CardanoSignedTx = 310 [(wire_out) = true]; + + // Ontology + MessageType_OntologyGetAddress = 350 [(wire_in) = true]; + MessageType_OntologyAddress = 351 [(wire_out) = true]; + MessageType_OntologyGetPublicKey = 352 [(wire_in) = true]; + MessageType_OntologyPublicKey = 353 [(wire_out) = true]; + MessageType_OntologySignTransfer = 354 [(wire_in) = true]; + MessageType_OntologySignedTransfer = 355 [(wire_out) = true]; + MessageType_OntologySignWithdrawOng = 356 [(wire_in) = true]; + MessageType_OntologySignedWithdrawOng = 357 [(wire_out) = true]; + MessageType_OntologySignOntIdRegister = 358 [(wire_in) = true]; + MessageType_OntologySignedOntIdRegister = 359 [(wire_out) = true]; + MessageType_OntologySignOntIdAddAttributes = 360 [(wire_in) = true]; + MessageType_OntologySignedOntIdAddAttributes = 361 [(wire_out) = true]; + + // Ripple + MessageType_RippleGetAddress = 400 [(wire_in) = true]; + MessageType_RippleAddress = 401 [(wire_out) = true]; + MessageType_RippleSignTx = 402 [(wire_in) = true]; + MessageType_RippleSignedTx = 403 [(wire_in) = true]; + + // Monero + MessageType_MoneroTransactionInitRequest = 501 [(wire_out) = true]; + MessageType_MoneroTransactionInitAck = 502 [(wire_out) = true]; + MessageType_MoneroTransactionSetInputRequest = 503 [(wire_out) = true]; + MessageType_MoneroTransactionSetInputAck = 504 [(wire_out) = true]; + MessageType_MoneroTransactionInputsPermutationRequest = 505 [(wire_out) = true]; + MessageType_MoneroTransactionInputsPermutationAck = 506 [(wire_out) = true]; + MessageType_MoneroTransactionInputViniRequest = 507 [(wire_out) = true]; + MessageType_MoneroTransactionInputViniAck = 508 [(wire_out) = true]; + MessageType_MoneroTransactionAllInputsSetRequest = 509 [(wire_out) = true]; + MessageType_MoneroTransactionAllInputsSetAck = 510 [(wire_out) = true]; + MessageType_MoneroTransactionSetOutputRequest = 511 [(wire_out) = true]; + MessageType_MoneroTransactionSetOutputAck = 512 [(wire_out) = true]; + MessageType_MoneroTransactionAllOutSetRequest = 513 [(wire_out) = true]; + MessageType_MoneroTransactionAllOutSetAck = 514 [(wire_out) = true]; + MessageType_MoneroTransactionSignInputRequest = 515 [(wire_out) = true]; + MessageType_MoneroTransactionSignInputAck = 516 [(wire_out) = true]; + MessageType_MoneroTransactionFinalRequest = 517 [(wire_out) = true]; + MessageType_MoneroTransactionFinalAck = 518 [(wire_out) = true]; + MessageType_MoneroKeyImageExportInitRequest = 530 [(wire_out) = true]; + MessageType_MoneroKeyImageExportInitAck = 531 [(wire_out) = true]; + MessageType_MoneroKeyImageSyncStepRequest = 532 [(wire_out) = true]; + MessageType_MoneroKeyImageSyncStepAck = 533 [(wire_out) = true]; + MessageType_MoneroKeyImageSyncFinalRequest = 534 [(wire_out) = true]; + MessageType_MoneroKeyImageSyncFinalAck = 535 [(wire_out) = true]; + MessageType_MoneroGetAddress = 540 [(wire_in) = true]; + MessageType_MoneroAddress = 541 [(wire_out) = true]; + MessageType_MoneroGetWatchKey = 542 [(wire_in) = true]; + MessageType_MoneroWatchKey = 543 [(wire_out) = true]; + MessageType_DebugMoneroDiagRequest = 546 [(wire_in) = true]; + MessageType_DebugMoneroDiagAck = 547 [(wire_out) = true]; + MessageType_MoneroGetTxKeyRequest = 550 [(wire_in) = true]; + MessageType_MoneroGetTxKeyAck = 551 [(wire_out) = true]; + MessageType_MoneroLiveRefreshStartRequest = 552 [(wire_in) = true]; + MessageType_MoneroLiveRefreshStartAck = 553 [(wire_out) = true]; + MessageType_MoneroLiveRefreshStepRequest = 554 [(wire_in) = true]; + MessageType_MoneroLiveRefreshStepAck = 555 [(wire_out) = true]; + MessageType_MoneroLiveRefreshFinalRequest = 556 [(wire_in) = true]; + MessageType_MoneroLiveRefreshFinalAck = 557 [(wire_out) = true]; + + // EOS + MessageType_EosGetPublicKey = 600 [(wire_in) = true]; + MessageType_EosPublicKey = 601 [(wire_out) = true]; + MessageType_EosSignTx = 602 [(wire_in) = true]; + MessageType_EosTxActionRequest = 603 [(wire_out) = true]; + MessageType_EosTxActionAck = 604 [(wire_in) = true]; + MessageType_EosSignedTx = 605 [(wire_out) = true]; + + // Binance + MessageType_BinanceGetAddress = 700 [(wire_in) = true]; + MessageType_BinanceAddress = 701 [(wire_out) = true]; + MessageType_BinanceGetPublicKey = 702 [(wire_in) = true]; + MessageType_BinancePublicKey = 703 [(wire_out) = true]; + MessageType_BinanceSignTx = 704 [(wire_in) = true]; + MessageType_BinanceTxRequest = 705 [(wire_out) = true]; + MessageType_BinanceTransferMsg = 706 [(wire_in) = true]; + MessageType_BinanceOrderMsg = 707 [(wire_in) = true]; + MessageType_BinanceCancelMsg = 708 [(wire_in) = true]; + MessageType_BinanceSignedTx = 709 [(wire_out) = true]; +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go new file mode 100644 index 000000000..7e756e609 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor/trezor.go @@ -0,0 +1,70 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains the implementation for interacting with the Trezor hardware +// wallets. The wire protocol spec can be found on the SatoshiLabs website: +// https://wiki.trezor.io/Developers_guide-Message_Workflows + +// !!! STAHP !!! +// +// Before you touch the protocol files, you need to be aware of a breaking change +// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10-> +// 2.1.0 (Model T). The Ethereum address representation was changed from the 20 +// byte binary blob to a 42 byte hex string. The upstream protocol buffer files +// only support the new format, so blindly pulling in a new spec will break old +// devices! +// +// The Trezor devs had the foresight to add the string version as a new message +// code instead of replacing the binary one. This means that the proto file can +// actually define both the old and the new versions as optional. Please ensure +// that you add back the old addresses everywhere (to avoid name clash. use the +// addressBin and addressHex names). +// +// If in doubt, reach out to @karalabe. + +// To regenerate the protocol files in this package: +// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases +// - Build with the usual `./configure && make` and ensure it's on your $PATH +// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor +// - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go` +// - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...` + +//go:generate protoc -I/usr/local/include:. --go_out=import_path=trezor:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto + +// Package trezor contains the wire protocol. +package trezor + +import ( + "reflect" + + "github.com/golang/protobuf/proto" +) + +// Type returns the protocol buffer type number of a specific message. If the +// message is nil, this method panics! +func Type(msg proto.Message) uint16 { + return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()]) +} + +// Name returns the friendly message type name of a specific protocol buffer +// type number. +func Name(kind uint16) string { + name := MessageType_name[int32(kind)] + if len(name) < 12 { + return name + } + return name[12:] +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go index 6cef6e0fb..ee539d965 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/wallet.go @@ -29,8 +29,9 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" - "github.com/karalabe/hid" + "github.com/karalabe/usb" ) // Maximum time between wallet health checks to detect USB unplugs. @@ -76,17 +77,17 @@ type wallet struct { driver driver // Hardware implementation of the low level device operations url *accounts.URL // Textual URL uniquely identifying this wallet - info hid.DeviceInfo // Known USB device infos about the wallet - device *hid.Device // USB device advertising itself as a hardware wallet + info usb.DeviceInfo // Known USB device infos about the wallet + device usb.Device // USB device advertising itself as a hardware wallet accounts []accounts.Account // List of derive accounts pinned on the hardware wallet paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations - deriveNextPath accounts.DerivationPath // Next derivation path for account auto-discovery - deriveNextAddr common.Address // Next derived account address for auto-discovery - deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with - deriveReq chan chan struct{} // Channel to request a self-derivation on - deriveQuit chan chan error // Channel to terminate the self-deriver with + deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported) + deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported) + deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with + deriveReq chan chan struct{} // Channel to request a self-derivation on + deriveQuit chan chan error // Channel to terminate the self-deriver with healthQuit chan chan error @@ -273,9 +274,7 @@ func (w *wallet) close() error { w.device = nil w.accounts, w.paths = nil, nil - w.driver.Close() - - return nil + return w.driver.Close() } // Accounts implements accounts.Wallet, returning the list of accounts pinned to @@ -340,57 +339,62 @@ func (w *wallet) selfDerive() { accs []accounts.Account paths []accounts.DerivationPath - nextAddr = w.deriveNextAddr - nextPath = w.deriveNextPath + nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...) + nextAddrs = append([]common.Address{}, w.deriveNextAddrs...) context = context.Background() ) - for empty := false; !empty; { - // Retrieve the next derived Ethereum account - if nextAddr == (common.Address{}) { - if nextAddr, err = w.driver.Derive(nextPath); err != nil { - w.log.Warn("USB wallet account derivation failed", "err", err) + for i := 0; i < len(nextAddrs); i++ { + for empty := false; !empty; { + // Retrieve the next derived Ethereum account + if nextAddrs[i] == (common.Address{}) { + if nextAddrs[i], err = w.driver.Derive(nextPaths[i]); err != nil { + w.log.Warn("USB wallet account derivation failed", "err", err) + break + } + } + // Check the account's status against the current chain state + var ( + balance *big.Int + nonce uint64 + ) + balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil) + if err != nil { + w.log.Warn("USB wallet balance retrieval failed", "err", err) break } - } - // Check the account's status against the current chain state - var ( - balance *big.Int - nonce uint64 - ) - balance, err = w.deriveChain.BalanceAt(context, nextAddr, nil) - if err != nil { - w.log.Warn("USB wallet balance retrieval failed", "err", err) - break - } - nonce, err = w.deriveChain.NonceAt(context, nextAddr, nil) - if err != nil { - w.log.Warn("USB wallet nonce retrieval failed", "err", err) - break - } - // If the next account is empty, stop self-derivation, but add it nonetheless - if balance.Sign() == 0 && nonce == 0 { - empty = true - } - // We've just self-derived a new account, start tracking it locally - path := make(accounts.DerivationPath, len(nextPath)) - copy(path[:], nextPath[:]) - paths = append(paths, path) + nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil) + if err != nil { + w.log.Warn("USB wallet nonce retrieval failed", "err", err) + break + } + // If the next account is empty, stop self-derivation, but add for the last base path + if balance.Sign() == 0 && nonce == 0 { + empty = true + if i < len(nextAddrs)-1 { + break + } + } + // We've just self-derived a new account, start tracking it locally + path := make(accounts.DerivationPath, len(nextPaths[i])) + copy(path[:], nextPaths[i][:]) + paths = append(paths, path) - account := accounts.Account{ - Address: nextAddr, - URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, - } - accs = append(accs, account) + account := accounts.Account{ + Address: nextAddrs[i], + URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, + } + accs = append(accs, account) - // Display a log message to the user for new (or previously empty accounts) - if _, known := w.paths[nextAddr]; !known || (!empty && nextAddr == w.deriveNextAddr) { - w.log.Info("USB wallet discovered new account", "address", nextAddr, "path", path, "balance", balance, "nonce", nonce) - } - // Fetch the next potential account - if !empty { - nextAddr = common.Address{} - nextPath[len(nextPath)-1]++ + // Display a log message to the user for new (or previously empty accounts) + if _, known := w.paths[nextAddrs[i]]; !known || (!empty && nextAddrs[i] == w.deriveNextAddrs[i]) { + w.log.Info("USB wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce) + } + // Fetch the next potential account + if !empty { + nextAddrs[i] = common.Address{} + nextPaths[i][len(nextPaths[i])-1]++ + } } } // Self derivation complete, release device lock @@ -407,8 +411,8 @@ func (w *wallet) selfDerive() { } // Shift the self-derivation forward // TODO(karalabe): don't overwrite changes from wallet.SelfDerive - w.deriveNextAddr = nextAddr - w.deriveNextPath = nextPath + w.deriveNextAddrs = nextAddrs + w.deriveNextPaths = nextPaths w.stateLock.Unlock() // Notify the user of termination and loop after a bit of time (to avoid trashing) @@ -475,32 +479,61 @@ func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun if _, ok := w.paths[address]; !ok { w.accounts = append(w.accounts, account) - w.paths[address] = path + w.paths[address] = make(accounts.DerivationPath, len(path)) + copy(w.paths[address], path) } return account, nil } -// SelfDerive implements accounts.Wallet, trying to discover accounts that the -// user used previously (based on the chain state), but ones that he/she did not -// explicitly pin to the wallet manually. To avoid chain head monitoring, self -// derivation only runs during account listing (and even then throttled). -func (w *wallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) { +// SelfDerive sets a base account derivation path from which the wallet attempts +// to discover non zero accounts and automatically add them to list of tracked +// accounts. +// +// Note, self derivaton will increment the last component of the specified path +// opposed to decending into a child path to allow discovering accounts starting +// from non zero components. +// +// Some hardware wallets switched derivation paths through their evolution, so +// this method supports providing multiple bases to discover old user accounts +// too. Only the last base will be used to derive the next empty account. +// +// You can disable automatic account discovery by calling SelfDerive with a nil +// chain state reader. +func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { w.stateLock.Lock() defer w.stateLock.Unlock() - w.deriveNextPath = make(accounts.DerivationPath, len(base)) - copy(w.deriveNextPath[:], base[:]) - - w.deriveNextAddr = common.Address{} + w.deriveNextPaths = make([]accounts.DerivationPath, len(bases)) + for i, base := range bases { + w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base)) + copy(w.deriveNextPaths[i][:], base[:]) + } + w.deriveNextAddrs = make([]common.Address, len(bases)) w.deriveChain = chain } -// SignHash implements accounts.Wallet, however signing arbitrary data is not +// signHash implements accounts.Wallet, however signing arbitrary data is not // supported for hardware wallets, so this method will always return an error. -func (w *wallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) { +func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { return nil, accounts.ErrNotSupported } +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + return w.signHash(account, crypto.Keccak256(data)) +} + +// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given +// data with the given account using passphrase as extra authentication. +// Since USB wallets don't rely on passphrases, these are silently ignored. +func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return w.SignData(account, mimeType, data) +} + +func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + return w.signHash(account, accounts.TextHash(text)) +} + // SignTx implements accounts.Wallet. It sends the transaction over to the Ledger // wallet to request a confirmation from the user. It returns either the signed // transaction or a failure if the user denied the transaction. @@ -550,8 +583,8 @@ func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID // SignHashWithPassphrase implements accounts.Wallet, however signing arbitrary // data is not supported for Ledger wallets, so this method will always return // an error. -func (w *wallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { - return w.SignHash(account, hash) +func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return w.SignText(account, accounts.TextHash(text)) } // SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given diff --git a/vendor/github.com/ethereum/go-ethereum/appveyor.yml b/vendor/github.com/ethereum/go-ethereum/appveyor.yml index 9ed4f114e..7d7a575a1 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.11.5.windows-%GETH_ARCH%.zip - - 7z x go1.11.5.windows-%GETH_ARCH%.zip -y -oC:\ > NUL + - appveyor DownloadFile https://dl.google.com/go/go1.13.windows-%GETH_ARCH%.zip + - 7z x go1.13.windows-%GETH_ARCH%.zip -y -oC:\ > NUL - go version - gcc --version diff --git a/vendor/github.com/ethereum/go-ethereum/common/bytes.go b/vendor/github.com/ethereum/go-ethereum/common/bytes.go index c82e61624..fa457b92c 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/bytes.go +++ b/vendor/github.com/ethereum/go-ethereum/common/bytes.go @@ -43,10 +43,8 @@ func ToHexArray(b [][]byte) []string { // FromHex returns the bytes represented by the hexadecimal string s. // s may be prefixed with "0x". func FromHex(s string) []byte { - if len(s) > 1 { - if s[0:2] == "0x" || s[0:2] == "0X" { - s = s[2:] - } + if has0xPrefix(s) { + s = s[2:] } if len(s)%2 == 1 { s = "0" + s @@ -65,8 +63,8 @@ func CopyBytes(b []byte) (copiedBytes []byte) { return } -// hasHexPrefix validates str begins with '0x' or '0X'. -func hasHexPrefix(str string) bool { +// has0xPrefix validates str begins with '0x' or '0X'. +func has0xPrefix(str string) bool { return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') } @@ -136,3 +134,14 @@ func LeftPadBytes(slice []byte, l int) []byte { return padded } + +// TrimLeftZeroes returns a subslice of s without leading zeroes +func TrimLeftZeroes(s []byte) []byte { + idx := 0 + for ; idx < len(s); idx++ { + if s[idx] != 0 { + break + } + } + return s[idx:] +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go index 88dd0f56c..6b26fa00f 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_darwin.go @@ -1,4 +1,4 @@ -// Copyright 2019 The go-ethereum Authors +// Copyright 2016 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify diff --git a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go index 5da434237..0d8727138 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go +++ b/vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_freebsd.go @@ -43,7 +43,7 @@ func Raise(max uint64) (uint64, error) { if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { return 0, err } - return limit.Cur, nil + return uint64(limit.Cur), nil } // Current retrieves the number of file descriptors allowed to be opened by this diff --git a/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go index fbc21241c..777b08eca 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go +++ b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go @@ -72,6 +72,25 @@ func (b Bytes) String() string { return Encode(b) } +// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type. +func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Bytes) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + data, err := Decode(input) + if err != nil { + return err + } + *b = data + default: + err = fmt.Errorf("Unexpected type for Bytes: %v", input) + } + return err +} + // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out // determines the required input length. This function is commonly used to implement the // UnmarshalJSON method for fixed-size types. @@ -187,6 +206,25 @@ func (b *Big) String() string { return EncodeBig(b.ToInt()) } +// ImplementsGraphQLType returns true if Big implements the provided GraphQL type. +func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Big) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + return b.UnmarshalText([]byte(input)) + case int32: + var num big.Int + num.SetInt64(int64(input)) + *b = Big(num) + default: + err = fmt.Errorf("Unexpected type for BigInt: %v", input) + } + return err +} + // Uint64 marshals/unmarshals as a JSON string with 0x prefix. // The zero value marshals as "0x0". type Uint64 uint64 @@ -234,6 +272,23 @@ func (b Uint64) String() string { return EncodeUint64(uint64(b)) } +// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type. +func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (b *Uint64) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + return b.UnmarshalText([]byte(input)) + case int32: + *b = Uint64(input) + default: + err = fmt.Errorf("Unexpected type for Long: %v", input) + } + return err +} + // Uint marshals/unmarshals as a JSON string with 0x prefix. // The zero value marshals as "0x0". type Uint uint diff --git a/vendor/github.com/ethereum/go-ethereum/common/math/big.go b/vendor/github.com/ethereum/go-ethereum/common/math/big.go index 9d2e7946d..d31c59af1 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/math/big.go +++ b/vendor/github.com/ethereum/go-ethereum/common/math/big.go @@ -42,6 +42,13 @@ const ( // HexOrDecimal256 marshals big.Int as hex or decimal. type HexOrDecimal256 big.Int +// NewHexOrDecimal256 creates a new HexOrDecimal256 +func NewHexOrDecimal256(x int64) *HexOrDecimal256 { + b := big.NewInt(x) + h := HexOrDecimal256(*b) + return &h +} + // UnmarshalText implements encoding.TextUnmarshaler. func (i *HexOrDecimal256) UnmarshalText(input []byte) error { bigint, ok := ParseBig256(string(input)) diff --git a/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go b/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go index dcac59c6c..d0e0cd78b 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go +++ b/vendor/github.com/ethereum/go-ethereum/common/mclock/mclock.go @@ -36,28 +36,39 @@ func (t AbsTime) Add(d time.Duration) AbsTime { return t + AbsTime(d) } -// Clock interface makes it possible to replace the monotonic system clock with +// The Clock interface makes it possible to replace the monotonic system clock with // a simulated clock. type Clock interface { Now() AbsTime Sleep(time.Duration) After(time.Duration) <-chan time.Time + AfterFunc(d time.Duration, f func()) Timer +} + +// Timer represents a cancellable event returned by AfterFunc +type Timer interface { + Stop() bool } // System implements Clock using the system clock. type System struct{} -// Now implements Clock. +// Now returns the current monotonic time. func (System) Now() AbsTime { return AbsTime(monotime.Now()) } -// Sleep implements Clock. +// Sleep blocks for the given duration. func (System) Sleep(d time.Duration) { time.Sleep(d) } -// After implements Clock. +// After returns a channel which receives the current time after d has elapsed. func (System) After(d time.Duration) <-chan time.Time { return time.After(d) } + +// AfterFunc runs f on a new goroutine after the duration has elapsed. +func (System) AfterFunc(d time.Duration, f func()) Timer { + return time.AfterFunc(d, f) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go b/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go index e014f5615..4d351252f 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go +++ b/vendor/github.com/ethereum/go-ethereum/common/mclock/simclock.go @@ -32,35 +32,45 @@ import ( // the timeout using a channel or semaphore. type Simulated struct { now AbsTime - scheduled []event + scheduled []*simTimer mu sync.RWMutex cond *sync.Cond + lastId uint64 } -type event struct { +// simTimer implements Timer on the virtual clock. +type simTimer struct { do func() at AbsTime + id uint64 + s *Simulated } // Run moves the clock by the given duration, executing all timers before that duration. func (s *Simulated) Run(d time.Duration) { s.mu.Lock() - defer s.mu.Unlock() s.init() end := s.now + AbsTime(d) + var do []func() for len(s.scheduled) > 0 { ev := s.scheduled[0] if ev.at > end { break } s.now = ev.at - ev.do() + do = append(do, ev.do) s.scheduled = s.scheduled[1:] } s.now = end + s.mu.Unlock() + + for _, fn := range do { + fn() + } } +// ActiveTimers returns the number of timers that haven't fired. func (s *Simulated) ActiveTimers() int { s.mu.RLock() defer s.mu.RUnlock() @@ -68,6 +78,7 @@ func (s *Simulated) ActiveTimers() int { return len(s.scheduled) } +// WaitForTimers waits until the clock has at least n scheduled timers. func (s *Simulated) WaitForTimers(n int) { s.mu.Lock() defer s.mu.Unlock() @@ -78,7 +89,7 @@ func (s *Simulated) WaitForTimers(n int) { } } -// Now implements Clock. +// Now returns the current virtual time. func (s *Simulated) Now() AbsTime { s.mu.RLock() defer s.mu.RUnlock() @@ -86,40 +97,62 @@ func (s *Simulated) Now() AbsTime { return s.now } -// Sleep implements Clock. +// Sleep blocks until the clock has advanced by d. func (s *Simulated) Sleep(d time.Duration) { <-s.After(d) } -// After implements Clock. +// After returns a channel which receives the current time after the clock +// has advanced by d. func (s *Simulated) After(d time.Duration) <-chan time.Time { after := make(chan time.Time, 1) - s.insert(d, func() { + s.AfterFunc(d, func() { after <- (time.Time{}).Add(time.Duration(s.now)) }) return after } -func (s *Simulated) insert(d time.Duration, do func()) { +// AfterFunc runs fn after the clock has advanced by d. Unlike with the system +// clock, fn runs on the goroutine that calls Run. +func (s *Simulated) AfterFunc(d time.Duration, fn func()) Timer { s.mu.Lock() defer s.mu.Unlock() s.init() at := s.now + AbsTime(d) + s.lastId++ + id := s.lastId l, h := 0, len(s.scheduled) ll := h for l != h { m := (l + h) / 2 - if at < s.scheduled[m].at { + if (at < s.scheduled[m].at) || ((at == s.scheduled[m].at) && (id < s.scheduled[m].id)) { h = m } else { l = m + 1 } } - s.scheduled = append(s.scheduled, event{}) + ev := &simTimer{do: fn, at: at, s: s} + s.scheduled = append(s.scheduled, nil) copy(s.scheduled[l+1:], s.scheduled[l:ll]) - s.scheduled[l] = event{do: do, at: at} + s.scheduled[l] = ev s.cond.Broadcast() + return ev +} + +func (ev *simTimer) Stop() bool { + s := ev.s + s.mu.Lock() + defer s.mu.Unlock() + + for i := 0; i < len(s.scheduled); i++ { + if s.scheduled[i] == ev { + s.scheduled = append(s.scheduled[:i], s.scheduled[i+1:]...) + s.cond.Broadcast() + return true + } + } + return false } func (s *Simulated) init() { diff --git a/vendor/github.com/ethereum/go-ethereum/common/prque/lazyqueue.go b/vendor/github.com/ethereum/go-ethereum/common/prque/lazyqueue.go new file mode 100644 index 000000000..92ddd77f6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/prque/lazyqueue.go @@ -0,0 +1,182 @@ +// Copyright 2019 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 prque + +import ( + "container/heap" + "time" + + "github.com/ethereum/go-ethereum/common/mclock" +) + +// LazyQueue is a priority queue data structure where priorities can change over +// time and are only evaluated on demand. +// Two callbacks are required: +// - priority evaluates the actual priority of an item +// - maxPriority gives an upper estimate for the priority in any moment between +// now and the given absolute time +// If the upper estimate is exceeded then Update should be called for that item. +// A global Refresh function should also be called periodically. +type LazyQueue struct { + clock mclock.Clock + // Items are stored in one of two internal queues ordered by estimated max + // priority until the next and the next-after-next refresh. Update and Refresh + // always places items in queue[1]. + queue [2]*sstack + popQueue *sstack + period time.Duration + maxUntil mclock.AbsTime + indexOffset int + setIndex SetIndexCallback + priority PriorityCallback + maxPriority MaxPriorityCallback +} + +type ( + PriorityCallback func(data interface{}, now mclock.AbsTime) int64 // actual priority callback + MaxPriorityCallback func(data interface{}, until mclock.AbsTime) int64 // estimated maximum priority callback +) + +// NewLazyQueue creates a new lazy queue +func NewLazyQueue(setIndex SetIndexCallback, priority PriorityCallback, maxPriority MaxPriorityCallback, clock mclock.Clock, refreshPeriod time.Duration) *LazyQueue { + q := &LazyQueue{ + popQueue: newSstack(nil), + setIndex: setIndex, + priority: priority, + maxPriority: maxPriority, + clock: clock, + period: refreshPeriod} + q.Reset() + q.Refresh() + return q +} + +// Reset clears the contents of the queue +func (q *LazyQueue) Reset() { + q.queue[0] = newSstack(q.setIndex0) + q.queue[1] = newSstack(q.setIndex1) +} + +// Refresh should be called at least with the frequency specified by the refreshPeriod parameter +func (q *LazyQueue) Refresh() { + q.maxUntil = q.clock.Now() + mclock.AbsTime(q.period) + for q.queue[0].Len() != 0 { + q.Push(heap.Pop(q.queue[0]).(*item).value) + } + q.queue[0], q.queue[1] = q.queue[1], q.queue[0] + q.indexOffset = 1 - q.indexOffset + q.maxUntil += mclock.AbsTime(q.period) +} + +// Push adds an item to the queue +func (q *LazyQueue) Push(data interface{}) { + heap.Push(q.queue[1], &item{data, q.maxPriority(data, q.maxUntil)}) +} + +// Update updates the upper priority estimate for the item with the given queue index +func (q *LazyQueue) Update(index int) { + q.Push(q.Remove(index)) +} + +// Pop removes and returns the item with the greatest actual priority +func (q *LazyQueue) Pop() (interface{}, int64) { + var ( + resData interface{} + resPri int64 + ) + q.MultiPop(func(data interface{}, priority int64) bool { + resData = data + resPri = priority + return false + }) + return resData, resPri +} + +// peekIndex returns the index of the internal queue where the item with the +// highest estimated priority is or -1 if both are empty +func (q *LazyQueue) peekIndex() int { + if q.queue[0].Len() != 0 { + if q.queue[1].Len() != 0 && q.queue[1].blocks[0][0].priority > q.queue[0].blocks[0][0].priority { + return 1 + } + return 0 + } + if q.queue[1].Len() != 0 { + return 1 + } + return -1 +} + +// MultiPop pops multiple items from the queue and is more efficient than calling +// Pop multiple times. Popped items are passed to the callback. MultiPop returns +// when the callback returns false or there are no more items to pop. +func (q *LazyQueue) MultiPop(callback func(data interface{}, priority int64) bool) { + now := q.clock.Now() + nextIndex := q.peekIndex() + for nextIndex != -1 { + data := heap.Pop(q.queue[nextIndex]).(*item).value + heap.Push(q.popQueue, &item{data, q.priority(data, now)}) + nextIndex = q.peekIndex() + for q.popQueue.Len() != 0 && (nextIndex == -1 || q.queue[nextIndex].blocks[0][0].priority < q.popQueue.blocks[0][0].priority) { + i := heap.Pop(q.popQueue).(*item) + if !callback(i.value, i.priority) { + for q.popQueue.Len() != 0 { + q.Push(heap.Pop(q.popQueue).(*item).value) + } + return + } + } + } +} + +// PopItem pops the item from the queue only, dropping the associated priority value. +func (q *LazyQueue) PopItem() interface{} { + i, _ := q.Pop() + return i +} + +// Remove removes removes the item with the given index. +func (q *LazyQueue) Remove(index int) interface{} { + if index < 0 { + return nil + } + return heap.Remove(q.queue[index&1^q.indexOffset], index>>1).(*item).value +} + +// Empty checks whether the priority queue is empty. +func (q *LazyQueue) Empty() bool { + return q.queue[0].Len() == 0 && q.queue[1].Len() == 0 +} + +// Size returns the number of items in the priority queue. +func (q *LazyQueue) Size() int { + return q.queue[0].Len() + q.queue[1].Len() +} + +// setIndex0 translates internal queue item index to the virtual index space of LazyQueue +func (q *LazyQueue) setIndex0(data interface{}, index int) { + if index == -1 { + q.setIndex(data, -1) + } else { + q.setIndex(data, index+index) + } +} + +// setIndex1 translates internal queue item index to the virtual index space of LazyQueue +func (q *LazyQueue) setIndex1(data interface{}, index int) { + q.setIndex(data, index+index+1) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/prque/prque.go b/vendor/github.com/ethereum/go-ethereum/common/prque/prque.go index 9fd31a2e5..3cc5a1ada 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/prque/prque.go +++ b/vendor/github.com/ethereum/go-ethereum/common/prque/prque.go @@ -1,5 +1,20 @@ +// CookieJar - A contestant's algorithm toolbox +// Copyright (c) 2013 Peter Szilagyi. All rights reserved. +// +// CookieJar is dual licensed: use of this source code is governed by a BSD +// license that can be found in the LICENSE file. Alternatively, the CookieJar +// toolbox may be used in accordance with the terms and conditions contained +// in a signed written agreement between you and the author(s). + // This is a duplicated and slightly modified version of "gopkg.in/karalabe/cookiejar.v2/collections/prque". +// Package prque implements a priority queue data structure supporting arbitrary +// value types and int64 priorities. +// +// If you would like to use a min-priority queue, simply negate the priorities. +// +// Internally the queue is based on the standard heap package working on a +// sortable version of the block based stack. package prque import ( @@ -11,8 +26,8 @@ type Prque struct { cont *sstack } -// Creates a new priority queue. -func New(setIndex setIndexCallback) *Prque { +// New creates a new priority queue. +func New(setIndex SetIndexCallback) *Prque { return &Prque{newSstack(setIndex)} } @@ -21,6 +36,12 @@ func (p *Prque) Push(data interface{}, priority int64) { heap.Push(p.cont, &item{data, priority}) } +// Peek returns the value with the greates priority but does not pop it off. +func (p *Prque) Peek() (interface{}, int64) { + item := p.cont.blocks[0][0] + return item.value, item.priority +} + // Pops the value with the greates priority off the stack and returns it. // Currently no shrinking is done. func (p *Prque) Pop() (interface{}, int64) { diff --git a/vendor/github.com/ethereum/go-ethereum/common/prque/sstack.go b/vendor/github.com/ethereum/go-ethereum/common/prque/sstack.go index 4875dae99..8518af54f 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/prque/sstack.go +++ b/vendor/github.com/ethereum/go-ethereum/common/prque/sstack.go @@ -1,3 +1,11 @@ +// CookieJar - A contestant's algorithm toolbox +// Copyright (c) 2013 Peter Szilagyi. All rights reserved. +// +// CookieJar is dual licensed: use of this source code is governed by a BSD +// license that can be found in the LICENSE file. Alternatively, the CookieJar +// toolbox may be used in accordance with the terms and conditions contained +// in a signed written agreement between you and the author(s). + // This is a duplicated and slightly modified version of "gopkg.in/karalabe/cookiejar.v2/collections/prque". package prque @@ -14,16 +22,16 @@ type item struct { priority int64 } -// setIndexCallback is called when the element is moved to a new index. -// Providing setIndexCallback is optional, it is needed only if the application needs +// SetIndexCallback is called when the element is moved to a new index. +// Providing SetIndexCallback is optional, it is needed only if the application needs // to delete elements other than the top one. -type setIndexCallback func(a interface{}, i int) +type SetIndexCallback func(data interface{}, index int) // Internal sortable stack data structure. Implements the Push and Pop ops for // the stack (heap) functionality and the Len, Less and Swap methods for the // sortability requirements of the heaps. type sstack struct { - setIndex setIndexCallback + setIndex SetIndexCallback size int capacity int offset int @@ -33,7 +41,7 @@ type sstack struct { } // Creates a new, empty stack. -func newSstack(setIndex setIndexCallback) *sstack { +func newSstack(setIndex SetIndexCallback) *sstack { result := new(sstack) result.setIndex = setIndex result.active = make([]*item, blockSize) diff --git a/vendor/github.com/ethereum/go-ethereum/common/size.go b/vendor/github.com/ethereum/go-ethereum/common/size.go index bd0fc85c7..097b6304a 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/size.go +++ b/vendor/github.com/ethereum/go-ethereum/common/size.go @@ -26,10 +26,14 @@ type StorageSize float64 // String implements the stringer interface. func (s StorageSize) String() string { - if s > 1000000 { - return fmt.Sprintf("%.2f mB", s/1000000) - } else if s > 1000 { - return fmt.Sprintf("%.2f kB", s/1000) + if s > 1099511627776 { + return fmt.Sprintf("%.2f TiB", s/1099511627776) + } else if s > 1073741824 { + return fmt.Sprintf("%.2f GiB", s/1073741824) + } else if s > 1048576 { + return fmt.Sprintf("%.2f MiB", s/1048576) + } else if s > 1024 { + return fmt.Sprintf("%.2f KiB", s/1024) } else { return fmt.Sprintf("%.2f B", s) } @@ -38,10 +42,14 @@ func (s StorageSize) String() string { // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (s StorageSize) TerminalString() string { - if s > 1000000 { - return fmt.Sprintf("%.2fmB", s/1000000) - } else if s > 1000 { - return fmt.Sprintf("%.2fkB", s/1000) + if s > 1099511627776 { + return fmt.Sprintf("%.2fTiB", s/1099511627776) + } else if s > 1073741824 { + return fmt.Sprintf("%.2fGiB", s/1073741824) + } else if s > 1048576 { + return fmt.Sprintf("%.2fMiB", s/1048576) + } else if s > 1024 { + return fmt.Sprintf("%.2fKiB", s/1024) } else { return fmt.Sprintf("%.2fB", s) } diff --git a/vendor/github.com/ethereum/go-ethereum/common/types.go b/vendor/github.com/ethereum/go-ethereum/common/types.go index 0f4892d28..8ca51a05f 100644 --- a/vendor/github.com/ethereum/go-ethereum/common/types.go +++ b/vendor/github.com/ethereum/go-ethereum/common/types.go @@ -141,6 +141,21 @@ func (h Hash) Value() (driver.Value, error) { return h[:], nil } +// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. +func (_ Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (h *Hash) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + err = h.UnmarshalText([]byte(input)) + default: + err = fmt.Errorf("Unexpected type for Bytes32: %v", input) + } + return err +} + // UnprefixedHash allows marshaling a Hash without 0x prefix. type UnprefixedHash Hash @@ -178,7 +193,7 @@ func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } // IsHexAddress verifies whether a string can represent a valid hex-encoded // Ethereum address or not. func IsHexAddress(s string) bool { - if hasHexPrefix(s) { + if has0xPrefix(s) { s = s[2:] } return len(s) == 2*AddressLength && isHex(s) @@ -187,9 +202,6 @@ func IsHexAddress(s string) bool { // Bytes gets the string representation of the underlying address. func (a Address) Bytes() []byte { return a[:] } -// Big converts an address to a big integer. -func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } - // Hash converts an address to a hash by left-padding it with zeros. func (a Address) Hash() Hash { return BytesToHash(a[:]) } @@ -268,6 +280,21 @@ func (a Address) Value() (driver.Value, error) { return a[:], nil } +// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. +func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" } + +// UnmarshalGraphQL unmarshals the provided GraphQL query data. +func (a *Address) UnmarshalGraphQL(input interface{}) error { + var err error + switch input := input.(type) { + case string: + err = a.UnmarshalText([]byte(input)) + default: + err = fmt.Errorf("Unexpected type for Address: %v", input) + } + return err +} + // UnprefixedAddress allows marshaling an Address without 0x prefix. type UnprefixedAddress Address diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go b/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go index a18782474..02b6da35b 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/clique/clique.go @@ -20,6 +20,7 @@ package clique import ( "bytes" "errors" + "io" "math/big" "math/rand" "sync" @@ -54,8 +55,8 @@ const ( var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity + extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. @@ -136,40 +137,9 @@ var ( errRecentlySigned = errors.New("recently signed") ) -// SignerFn is a signer callback function to request a hash to be signed by a +// SignerFn is a signer callback function to request a header to be signed by a // backing account. -type SignerFn func(accounts.Account, []byte) ([]byte, error) - -// sigHash returns the hash which is used as input for the proof-of-authority -// signing. It is the hash of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func sigHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - - rlp.Encode(hasher, []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - }) - hasher.Sum(hash[:0]) - return hash -} +type SignerFn func(accounts.Account, string, []byte) ([]byte, error) // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { @@ -185,7 +155,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er signature := header.Extra[len(header.Extra)-extraSeal:] // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature) + pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) if err != nil { return common.Address{}, err } @@ -395,8 +365,11 @@ func (c *Clique) snapshot(chain consensus.ChainReader, number uint64, hash commo break } } - // If we're at an checkpoint block, make a snapshot if it's known - if number == 0 || (number%c.config.Epoch == 0 && chain.GetHeaderByNumber(number-1) == nil) { + // If we're at the genesis, snapshot the initial state. Alternatively if we're + // at a checkpoint block without a parent (light client CHT), or we have piled + // up more headers than allowed to be reorged (chain reinit from a freezer), + // consider the checkpoint trusted and snapshot it. + if number == 0 || (number%c.config.Epoch == 0 && (len(headers) > params.ImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { hash := checkpoint.Hash() @@ -578,8 +551,16 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro } // Finalize implements consensus.Engine, ensuring no uncles are set, nor block -// rewards given, and returns the final block. -func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +// rewards given. +func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + // No block rewards in PoA, so the state remains as is and uncles are dropped + header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + header.UncleHash = types.CalcUncleHash(nil) +} + +// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, +// nor block rewards given, and returns the final block. +func (c *Clique) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -646,7 +627,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) } // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes()) + sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeClique, CliqueRLP(header)) if err != nil { return err } @@ -663,7 +644,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c select { case results <- block.WithSeal(header): default: - log.Warn("Sealing result is not read by miner", "sealhash", c.SealHash(header)) + log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) } }() @@ -693,7 +674,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { // SealHash returns the hash of a block prior to it being sealed. func (c *Clique) SealHash(header *types.Header) common.Hash { - return sigHash(header) + return SealHash(header) } // Close implements consensus.Engine. It's a noop for clique as there are no background threads. @@ -711,3 +692,47 @@ func (c *Clique) APIs(chain consensus.ChainReader) []rpc.API { Public: false, }} } + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header) + hasher.Sum(hash[:0]) + return hash +} + +// CliqueRLP returns the rlp bytes which needs to be signed for the proof-of-authority +// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// Note, the method requires the extra data to be at least 65 bytes, otherwise it +// panics. This is done to avoid accidentally using both forms (signature present +// or not), which could be abused to produce different hashes for the same header. +func CliqueRLP(header *types.Header) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header) + return b.Bytes() +} + +func encodeSigHeader(w io.Writer, header *types.Header) { + err := rlp.Encode(w, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/clique/snapshot.go b/vendor/github.com/ethereum/go-ethereum/consensus/clique/snapshot.go index 54d4555f3..4ee731a90 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/clique/snapshot.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/clique/snapshot.go @@ -20,10 +20,12 @@ import ( "bytes" "encoding/json" "sort" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" lru "github.com/hashicorp/golang-lru" ) @@ -197,7 +199,11 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { // Iterate through the headers and create a new snapshot snap := s.copy() - for _, header := range headers { + var ( + start = time.Now() + logged = time.Now() + ) + for i, header := range headers { // Remove any votes on checkpoint blocks number := header.Number.Uint64() if number%s.config.Epoch == 0 { @@ -285,6 +291,14 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { } delete(snap.Tally, header.Coinbase) } + // If we're taking too much time (ecrecover), notify the user once a while + if time.Since(logged) > 8*time.Second { + log.Info("Reconstructing voting history", "processed", i, "total", len(headers), "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + if time.Since(start) > 8*time.Second { + log.Info("Reconstructed voting history", "processed", len(headers), "elapsed", common.PrettyDuration(time.Since(start))) } snap.Number += uint64(len(headers)) snap.Hash = headers[len(headers)-1].Hash() diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/consensus.go b/vendor/github.com/ethereum/go-ethereum/consensus/consensus.go index 487b07be7..f753af550 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/consensus.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/consensus.go @@ -80,10 +80,19 @@ type Engine interface { Prepare(chain ChainReader, header *types.Header) error // Finalize runs any post-transaction state modifications (e.g. block rewards) - // and assembles the final block. + // but does not assemble the block. + // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, + uncles []*types.Header) + + // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block + // rewards) and assembles the final block. + // + // Note: The block header and state database might be updated to reflect any + // consensus rules that happen at finalization (e.g. block rewards). + FinalizeAndAssemble(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go index fb9a396ae..d271518f4 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/consensus.go @@ -191,6 +191,9 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo if len(block.Uncles()) > maxUncles { return errTooManyUncles } + if len(block.Uncles()) == 0 { + return nil + } // Gather the set of past uncles and ancestors uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header) @@ -558,8 +561,16 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) } // Finalize implements consensus.Engine, accumulating the block and uncle rewards, -// setting the final state and assembling the block. -func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +// setting the final state on the header +func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + // Accumulate any block and uncle rewards and commit the final state root + accumulateRewards(chain.Config(), state, header, uncles) + header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) +} + +// FinalizeAndAssemble implements consensus.Engine, accumulating the block and +// uncle rewards, setting the final state and assembling the block. +func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/sealer.go b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/sealer.go index 3a0919ca9..43db1fcb7 100644 --- a/vendor/github.com/ethereum/go-ethereum/consensus/ethash/sealer.go +++ b/vendor/github.com/ethereum/go-ethereum/consensus/ethash/sealer.go @@ -270,7 +270,7 @@ func (ethash *Ethash) remote(notify []string, noverify bool) { start := time.Now() if !noverify { if err := ethash.verifySeal(nil, header, true); err != nil { - log.Warn("Invalid proof-of-work submitted", "sealhash", sealhash, "elapsed", time.Since(start), "err", err) + log.Warn("Invalid proof-of-work submitted", "sealhash", sealhash, "elapsed", common.PrettyDuration(time.Since(start)), "err", err) return false } } @@ -279,7 +279,7 @@ func (ethash *Ethash) remote(notify []string, noverify bool) { log.Warn("Ethash result channel is empty, submitted mining result is rejected") return false } - log.Trace("Verified correct proof-of-work", "sealhash", sealhash, "elapsed", time.Since(start)) + log.Trace("Verified correct proof-of-work", "sealhash", sealhash, "elapsed", common.PrettyDuration(time.Since(start))) // Solutions seems to be valid, return to the miner and notify acceptance. solution := block.WithSeal(header) diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.go b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.go new file mode 100644 index 000000000..3bb351792 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.go @@ -0,0 +1,415 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// CheckpointOracleABI is the input ABI used to generate the binding from. +const CheckpointOracleABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"GetAllAdmin\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetLatestCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_recentNumber\",\"type\":\"uint256\"},{\"name\":\"_recentHash\",\"type\":\"bytes32\"},{\"name\":\"_hash\",\"type\":\"bytes32\"},{\"name\":\"_sectionIndex\",\"type\":\"uint64\"},{\"name\":\"v\",\"type\":\"uint8[]\"},{\"name\":\"r\",\"type\":\"bytes32[]\"},{\"name\":\"s\",\"type\":\"bytes32[]\"}],\"name\":\"SetCheckpoint\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_adminlist\",\"type\":\"address[]\"},{\"name\":\"_sectionSize\",\"type\":\"uint256\"},{\"name\":\"_processConfirms\",\"type\":\"uint256\"},{\"name\":\"_threshold\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"index\",\"type\":\"uint64\"},{\"indexed\":false,\"name\":\"checkpointHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"v\",\"type\":\"uint8\"},{\"indexed\":false,\"name\":\"r\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"NewCheckpointVote\",\"type\":\"event\"}]" + +// CheckpointOracleBin is the compiled bytecode used for deploying new contracts. +const CheckpointOracleBin = `0x608060405234801561001057600080fd5b506040516108153803806108158339818101604052608081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8201602081018481111561005e57600080fd5b815185602082028301116401000000008211171561007b57600080fd5b505060208201516040830151606090930151919450925060005b84518110156101415760016000808784815181106100af57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060018582815181106100fc57fe5b60209081029190910181015182546001808201855560009485529290932090920180546001600160a01b0319166001600160a01b039093169290921790915501610095565b50600592909255600655600755506106b78061015e6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806345848dfc146100465780634d6a304c1461009e578063d459fc46146100cf575b600080fd5b61004e6102b0565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561008a578181015183820152602001610072565b505050509050019250505060405180910390f35b6100a661034f565b6040805167ffffffffffffffff9094168452602084019290925282820152519081900360600190f35b61029c600480360360e08110156100e557600080fd5b81359160208101359160408201359167ffffffffffffffff6060820135169181019060a08101608082013564010000000081111561012257600080fd5b82018360208201111561013457600080fd5b8035906020019184602083028401116401000000008311171561015657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156101a657600080fd5b8201836020820111156101b857600080fd5b803590602001918460208302840111640100000000831117156101da57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561022a57600080fd5b82018360208201111561023c57600080fd5b8035906020019184602083028401116401000000008311171561025e57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061036a945050505050565b604080519115158252519081900360200190f35b6060806001805490506040519080825280602002602001820160405280156102e2578160200160208202803883390190505b50905060005b60015481101561034957600181815481106102ff57fe5b9060005260206000200160009054906101000a90046001600160a01b031682828151811061032957fe5b6001600160a01b03909216602092830291909101909101526001016102e8565b50905090565b60025460045460035467ffffffffffffffff90921691909192565b3360009081526020819052604081205460ff1661038657600080fd5b8688401461039357600080fd5b82518451146103a157600080fd5b81518451146103af57600080fd5b6006546005548660010167ffffffffffffffff1602014310156103d457506000610677565b60025467ffffffffffffffff90811690861610156103f457506000610677565b60025467ffffffffffffffff8681169116148015610426575067ffffffffffffffff8516151580610426575060035415155b1561043357506000610677565b8561044057506000610677565b60408051601960f81b6020808301919091526000602183018190523060601b60228401526001600160c01b031960c08a901b166036840152603e8084018b905284518085039091018152605e909301909352815191012090805b86518110156106715760006001848984815181106104b457fe5b60200260200101518985815181106104c857fe5b60200260200101518986815181106104dc57fe5b602002602001015160405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561053b573d6000803e3d6000fd5b505060408051601f1901516001600160a01b03811660009081526020819052919091205490925060ff16905061057057600080fd5b826001600160a01b0316816001600160a01b03161161058e57600080fd5b8092508867ffffffffffffffff167fce51ffa16246bcaf0899f6504f473cd0114f430f566cef71ab7e03d3dde42a418b8a85815181106105ca57fe5b60200260200101518a86815181106105de57fe5b60200260200101518a87815181106105f257fe5b6020026020010151604051808581526020018460ff1660ff16815260200183815260200182815260200194505050505060405180910390a260075482600101106106685750505060048790555050436003556002805467ffffffffffffffff191667ffffffffffffffff86161790556001610677565b5060010161049a565b50600080fd5b97965050505050505056fea265627a7a723058207f6a191ce575596a2f1e907c8c0a01003d16b69fb2c4f432d10878e8c0a99a0264736f6c634300050a0032` + +// DeployCheckpointOracle deploys a new Ethereum contract, binding an instance of CheckpointOracle to it. +func DeployCheckpointOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _adminlist []common.Address, _sectionSize *big.Int, _processConfirms *big.Int, _threshold *big.Int) (common.Address, *types.Transaction, *CheckpointOracle, error) { + parsed, err := abi.JSON(strings.NewReader(CheckpointOracleABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(CheckpointOracleBin), backend, _adminlist, _sectionSize, _processConfirms, _threshold) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CheckpointOracle{CheckpointOracleCaller: CheckpointOracleCaller{contract: contract}, CheckpointOracleTransactor: CheckpointOracleTransactor{contract: contract}, CheckpointOracleFilterer: CheckpointOracleFilterer{contract: contract}}, nil +} + +// CheckpointOracle is an auto generated Go binding around an Ethereum contract. +type CheckpointOracle struct { + CheckpointOracleCaller // Read-only binding to the contract + CheckpointOracleTransactor // Write-only binding to the contract + CheckpointOracleFilterer // Log filterer for contract events +} + +// CheckpointOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type CheckpointOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CheckpointOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CheckpointOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CheckpointOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CheckpointOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CheckpointOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CheckpointOracleSession struct { + Contract *CheckpointOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CheckpointOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CheckpointOracleCallerSession struct { + Contract *CheckpointOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CheckpointOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CheckpointOracleTransactorSession struct { + Contract *CheckpointOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CheckpointOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type CheckpointOracleRaw struct { + Contract *CheckpointOracle // Generic contract binding to access the raw methods on +} + +// CheckpointOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CheckpointOracleCallerRaw struct { + Contract *CheckpointOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// CheckpointOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CheckpointOracleTransactorRaw struct { + Contract *CheckpointOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCheckpointOracle creates a new instance of CheckpointOracle, bound to a specific deployed contract. +func NewCheckpointOracle(address common.Address, backend bind.ContractBackend) (*CheckpointOracle, error) { + contract, err := bindCheckpointOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CheckpointOracle{CheckpointOracleCaller: CheckpointOracleCaller{contract: contract}, CheckpointOracleTransactor: CheckpointOracleTransactor{contract: contract}, CheckpointOracleFilterer: CheckpointOracleFilterer{contract: contract}}, nil +} + +// NewCheckpointOracleCaller creates a new read-only instance of CheckpointOracle, bound to a specific deployed contract. +func NewCheckpointOracleCaller(address common.Address, caller bind.ContractCaller) (*CheckpointOracleCaller, error) { + contract, err := bindCheckpointOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CheckpointOracleCaller{contract: contract}, nil +} + +// NewCheckpointOracleTransactor creates a new write-only instance of CheckpointOracle, bound to a specific deployed contract. +func NewCheckpointOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*CheckpointOracleTransactor, error) { + contract, err := bindCheckpointOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CheckpointOracleTransactor{contract: contract}, nil +} + +// NewCheckpointOracleFilterer creates a new log filterer instance of CheckpointOracle, bound to a specific deployed contract. +func NewCheckpointOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*CheckpointOracleFilterer, error) { + contract, err := bindCheckpointOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CheckpointOracleFilterer{contract: contract}, nil +} + +// bindCheckpointOracle binds a generic wrapper to an already deployed contract. +func bindCheckpointOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(CheckpointOracleABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CheckpointOracle *CheckpointOracleRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _CheckpointOracle.Contract.CheckpointOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CheckpointOracle *CheckpointOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CheckpointOracle.Contract.CheckpointOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CheckpointOracle *CheckpointOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CheckpointOracle.Contract.CheckpointOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CheckpointOracle *CheckpointOracleCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _CheckpointOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CheckpointOracle *CheckpointOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CheckpointOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CheckpointOracle *CheckpointOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CheckpointOracle.Contract.contract.Transact(opts, method, params...) +} + +// GetAllAdmin is a free data retrieval call binding the contract method 0x45848dfc. +// +// Solidity: function GetAllAdmin() constant returns(address[]) +func (_CheckpointOracle *CheckpointOracleCaller) GetAllAdmin(opts *bind.CallOpts) ([]common.Address, error) { + var ( + ret0 = new([]common.Address) + ) + out := ret0 + err := _CheckpointOracle.contract.Call(opts, out, "GetAllAdmin") + return *ret0, err +} + +// GetAllAdmin is a free data retrieval call binding the contract method 0x45848dfc. +// +// Solidity: function GetAllAdmin() constant returns(address[]) +func (_CheckpointOracle *CheckpointOracleSession) GetAllAdmin() ([]common.Address, error) { + return _CheckpointOracle.Contract.GetAllAdmin(&_CheckpointOracle.CallOpts) +} + +// GetAllAdmin is a free data retrieval call binding the contract method 0x45848dfc. +// +// Solidity: function GetAllAdmin() constant returns(address[]) +func (_CheckpointOracle *CheckpointOracleCallerSession) GetAllAdmin() ([]common.Address, error) { + return _CheckpointOracle.Contract.GetAllAdmin(&_CheckpointOracle.CallOpts) +} + +// GetLatestCheckpoint is a free data retrieval call binding the contract method 0x4d6a304c. +// +// Solidity: function GetLatestCheckpoint() constant returns(uint64, bytes32, uint256) +func (_CheckpointOracle *CheckpointOracleCaller) GetLatestCheckpoint(opts *bind.CallOpts) (uint64, [32]byte, *big.Int, error) { + var ( + ret0 = new(uint64) + ret1 = new([32]byte) + ret2 = new(*big.Int) + ) + out := &[]interface{}{ + ret0, + ret1, + ret2, + } + err := _CheckpointOracle.contract.Call(opts, out, "GetLatestCheckpoint") + return *ret0, *ret1, *ret2, err +} + +// GetLatestCheckpoint is a free data retrieval call binding the contract method 0x4d6a304c. +// +// Solidity: function GetLatestCheckpoint() constant returns(uint64, bytes32, uint256) +func (_CheckpointOracle *CheckpointOracleSession) GetLatestCheckpoint() (uint64, [32]byte, *big.Int, error) { + return _CheckpointOracle.Contract.GetLatestCheckpoint(&_CheckpointOracle.CallOpts) +} + +// GetLatestCheckpoint is a free data retrieval call binding the contract method 0x4d6a304c. +// +// Solidity: function GetLatestCheckpoint() constant returns(uint64, bytes32, uint256) +func (_CheckpointOracle *CheckpointOracleCallerSession) GetLatestCheckpoint() (uint64, [32]byte, *big.Int, error) { + return _CheckpointOracle.Contract.GetLatestCheckpoint(&_CheckpointOracle.CallOpts) +} + +// SetCheckpoint is a paid mutator transaction binding the contract method 0xd459fc46. +// +// Solidity: function SetCheckpoint(uint256 _recentNumber, bytes32 _recentHash, bytes32 _hash, uint64 _sectionIndex, uint8[] v, bytes32[] r, bytes32[] s) returns(bool) +func (_CheckpointOracle *CheckpointOracleTransactor) SetCheckpoint(opts *bind.TransactOpts, _recentNumber *big.Int, _recentHash [32]byte, _hash [32]byte, _sectionIndex uint64, v []uint8, r [][32]byte, s [][32]byte) (*types.Transaction, error) { + return _CheckpointOracle.contract.Transact(opts, "SetCheckpoint", _recentNumber, _recentHash, _hash, _sectionIndex, v, r, s) +} + +// SetCheckpoint is a paid mutator transaction binding the contract method 0xd459fc46. +// +// Solidity: function SetCheckpoint(uint256 _recentNumber, bytes32 _recentHash, bytes32 _hash, uint64 _sectionIndex, uint8[] v, bytes32[] r, bytes32[] s) returns(bool) +func (_CheckpointOracle *CheckpointOracleSession) SetCheckpoint(_recentNumber *big.Int, _recentHash [32]byte, _hash [32]byte, _sectionIndex uint64, v []uint8, r [][32]byte, s [][32]byte) (*types.Transaction, error) { + return _CheckpointOracle.Contract.SetCheckpoint(&_CheckpointOracle.TransactOpts, _recentNumber, _recentHash, _hash, _sectionIndex, v, r, s) +} + +// SetCheckpoint is a paid mutator transaction binding the contract method 0xd459fc46. +// +// Solidity: function SetCheckpoint(uint256 _recentNumber, bytes32 _recentHash, bytes32 _hash, uint64 _sectionIndex, uint8[] v, bytes32[] r, bytes32[] s) returns(bool) +func (_CheckpointOracle *CheckpointOracleTransactorSession) SetCheckpoint(_recentNumber *big.Int, _recentHash [32]byte, _hash [32]byte, _sectionIndex uint64, v []uint8, r [][32]byte, s [][32]byte) (*types.Transaction, error) { + return _CheckpointOracle.Contract.SetCheckpoint(&_CheckpointOracle.TransactOpts, _recentNumber, _recentHash, _hash, _sectionIndex, v, r, s) +} + +// CheckpointOracleNewCheckpointVoteIterator is returned from FilterNewCheckpointVote and is used to iterate over the raw logs and unpacked data for NewCheckpointVote events raised by the CheckpointOracle contract. +type CheckpointOracleNewCheckpointVoteIterator struct { + Event *CheckpointOracleNewCheckpointVote // 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 *CheckpointOracleNewCheckpointVoteIterator) 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(CheckpointOracleNewCheckpointVote) + 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(CheckpointOracleNewCheckpointVote) + 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 *CheckpointOracleNewCheckpointVoteIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CheckpointOracleNewCheckpointVoteIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CheckpointOracleNewCheckpointVote represents a NewCheckpointVote event raised by the CheckpointOracle contract. +type CheckpointOracleNewCheckpointVote struct { + Index uint64 + CheckpointHash [32]byte + V uint8 + R [32]byte + S [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewCheckpointVote is a free log retrieval operation binding the contract event 0xce51ffa16246bcaf0899f6504f473cd0114f430f566cef71ab7e03d3dde42a41. +// +// Solidity: event NewCheckpointVote(uint64 indexed index, bytes32 checkpointHash, uint8 v, bytes32 r, bytes32 s) +func (_CheckpointOracle *CheckpointOracleFilterer) FilterNewCheckpointVote(opts *bind.FilterOpts, index []uint64) (*CheckpointOracleNewCheckpointVoteIterator, error) { + + var indexRule []interface{} + for _, indexItem := range index { + indexRule = append(indexRule, indexItem) + } + + logs, sub, err := _CheckpointOracle.contract.FilterLogs(opts, "NewCheckpointVote", indexRule) + if err != nil { + return nil, err + } + return &CheckpointOracleNewCheckpointVoteIterator{contract: _CheckpointOracle.contract, event: "NewCheckpointVote", logs: logs, sub: sub}, nil +} + +// WatchNewCheckpointVote is a free log subscription operation binding the contract event 0xce51ffa16246bcaf0899f6504f473cd0114f430f566cef71ab7e03d3dde42a41. +// +// Solidity: event NewCheckpointVote(uint64 indexed index, bytes32 checkpointHash, uint8 v, bytes32 r, bytes32 s) +func (_CheckpointOracle *CheckpointOracleFilterer) WatchNewCheckpointVote(opts *bind.WatchOpts, sink chan<- *CheckpointOracleNewCheckpointVote, index []uint64) (event.Subscription, error) { + + var indexRule []interface{} + for _, indexItem := range index { + indexRule = append(indexRule, indexItem) + } + + logs, sub, err := _CheckpointOracle.contract.WatchLogs(opts, "NewCheckpointVote", indexRule) + 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(CheckpointOracleNewCheckpointVote) + if err := _CheckpointOracle.contract.UnpackLog(event, "NewCheckpointVote", 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 +} + +// ParseNewCheckpointVote is a log parse operation binding the contract event 0xce51ffa16246bcaf0899f6504f473cd0114f430f566cef71ab7e03d3dde42a41. +// +// Solidity: event NewCheckpointVote(uint64 indexed index, bytes32 checkpointHash, uint8 v, bytes32 r, bytes32 s) +func (_CheckpointOracle *CheckpointOracleFilterer) ParseNewCheckpointVote(log types.Log) (*CheckpointOracleNewCheckpointVote, error) { + event := new(CheckpointOracleNewCheckpointVote) + if err := _CheckpointOracle.contract.UnpackLog(event, "NewCheckpointVote", log); err != nil { + return nil, err + } + return event, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.sol b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.sol new file mode 100644 index 000000000..010644727 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract/oracle.sol @@ -0,0 +1,174 @@ +pragma solidity ^0.5.10; + +/** + * @title CheckpointOracle + * @author Gary Rong, Martin Swende + * @dev Implementation of the blockchain checkpoint registrar. + */ +contract CheckpointOracle { + /* + Events + */ + + // NewCheckpointVote is emitted when a new checkpoint proposal receives a vote. + event NewCheckpointVote(uint64 indexed index, bytes32 checkpointHash, uint8 v, bytes32 r, bytes32 s); + + /* + Public Functions + */ + constructor(address[] memory _adminlist, uint _sectionSize, uint _processConfirms, uint _threshold) public { + for (uint i = 0; i < _adminlist.length; i++) { + admins[_adminlist[i]] = true; + adminList.push(_adminlist[i]); + } + sectionSize = _sectionSize; + processConfirms = _processConfirms; + threshold = _threshold; + } + + /** + * @dev Get latest stable checkpoint information. + * @return section index + * @return checkpoint hash + * @return block height associated with checkpoint + */ + function GetLatestCheckpoint() + view + public + returns(uint64, bytes32, uint) { + return (sectionIndex, hash, height); + } + + // SetCheckpoint sets a new checkpoint. It accepts a list of signatures + // @_recentNumber: a recent blocknumber, for replay protection + // @_recentHash : the hash of `_recentNumber` + // @_hash : the hash to set at _sectionIndex + // @_sectionIndex : the section index to set + // @v : the list of v-values + // @r : the list or r-values + // @s : the list of s-values + function SetCheckpoint( + uint _recentNumber, + bytes32 _recentHash, + bytes32 _hash, + uint64 _sectionIndex, + uint8[] memory v, + bytes32[] memory r, + bytes32[] memory s) + public + returns (bool) + { + // Ensure the sender is authorized. + require(admins[msg.sender]); + + // These checks replay protection, so it cannot be replayed on forks, + // accidentally or intentionally + require(blockhash(_recentNumber) == _recentHash); + + // Ensure the batch of signatures are valid. + require(v.length == r.length); + require(v.length == s.length); + + // Filter out "future" checkpoint. + if (block.number < (_sectionIndex+1)*sectionSize+processConfirms) { + return false; + } + // Filter out "old" announcement + if (_sectionIndex < sectionIndex) { + return false; + } + // Filter out "stale" announcement + if (_sectionIndex == sectionIndex && (_sectionIndex != 0 || height != 0)) { + return false; + } + // Filter out "invalid" announcement + if (_hash == ""){ + return false; + } + + // EIP 191 style signatures + // + // Arguments when calculating hash to validate + // 1: byte(0x19) - the initial 0x19 byte + // 2: byte(0) - the version byte (data with intended validator) + // 3: this - the validator address + // -- Application specific data + // 4 : checkpoint section_index(uint64) + // 5 : checkpoint hash (bytes32) + // hash = keccak256(checkpoint_index, section_head, cht_root, bloom_root) + bytes32 signedHash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, _sectionIndex, _hash)); + + address lastVoter = address(0); + + // In order for us not to have to maintain a mapping of who has already + // voted, and we don't want to count a vote twice, the signatures must + // be submitted in strict ordering. + for (uint idx = 0; idx < v.length; idx++){ + address signer = ecrecover(signedHash, v[idx], r[idx], s[idx]); + require(admins[signer]); + require(uint256(signer) > uint256(lastVoter)); + lastVoter = signer; + emit NewCheckpointVote(_sectionIndex, _hash, v[idx], r[idx], s[idx]); + + // Sufficient signatures present, update latest checkpoint. + if (idx+1 >= threshold){ + hash = _hash; + height = block.number; + sectionIndex = _sectionIndex; + return true; + } + } + // We shouldn't wind up here, reverting un-emits the events + revert(); + } + + /** + * @dev Get all admin addresses + * @return address list + */ + function GetAllAdmin() + public + view + returns(address[] memory) + { + address[] memory ret = new address[](adminList.length); + for (uint i = 0; i < adminList.length; i++) { + ret[i] = adminList[i]; + } + return ret; + } + + /* + Fields + */ + // A map of admin users who have the permission to update CHT and bloom Trie root + mapping(address => bool) admins; + + // A list of admin users so that we can obtain all admin users. + address[] adminList; + + // Latest stored section id + uint64 sectionIndex; + + // The block height associated with latest registered checkpoint. + uint height; + + // The hash of latest registered checkpoint. + bytes32 hash; + + // The frequency for creating a checkpoint + // + // The default value should be the same as the checkpoint size(32768) in the ethereum. + uint sectionSize; + + // The number of confirmations needed before a checkpoint can be registered. + // We have to make sure the checkpoint registered will not be invalid due to + // chain reorg. + // + // The default value should be the same as the checkpoint process confirmations(256) + // in the ethereum. + uint processConfirms; + + // The required signatures to finalize a stable checkpoint. + uint threshold; +} diff --git a/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/oracle.go b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/oracle.go new file mode 100644 index 000000000..2d725397b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/contracts/checkpointoracle/oracle.go @@ -0,0 +1,90 @@ +// Copyright 2019 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 checkpointoracle is a an on-chain light client checkpoint oracle. +package checkpointoracle + +//go:generate abigen --sol contract/oracle.sol --pkg contract --out contract/oracle.go + +import ( + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract" + "github.com/ethereum/go-ethereum/core/types" +) + +// CheckpointOracle is a Go wrapper around an on-chain light client checkpoint oracle. +type CheckpointOracle struct { + contract *contract.CheckpointOracle +} + +// NewCheckpointOracle binds checkpoint contract and returns a registrar instance. +func NewCheckpointOracle(contractAddr common.Address, backend bind.ContractBackend) (*CheckpointOracle, error) { + c, err := contract.NewCheckpointOracle(contractAddr, backend) + if err != nil { + return nil, err + } + return &CheckpointOracle{contract: c}, nil +} + +// Contract returns the underlying contract instance. +func (oracle *CheckpointOracle) Contract() *contract.CheckpointOracle { + return oracle.contract +} + +// LookupCheckpointEvents searches checkpoint event for specific section in the +// given log batches. +func (oracle *CheckpointOracle) LookupCheckpointEvents(blockLogs [][]*types.Log, section uint64, hash common.Hash) []*contract.CheckpointOracleNewCheckpointVote { + var votes []*contract.CheckpointOracleNewCheckpointVote + + for _, logs := range blockLogs { + for _, log := range logs { + event, err := oracle.contract.ParseNewCheckpointVote(*log) + if err != nil { + continue + } + if event.Index == section && common.Hash(event.CheckpointHash) == hash { + votes = append(votes, event) + } + } + } + return votes +} + +// RegisterCheckpoint registers the checkpoint with a batch of associated signatures +// that are collected off-chain and sorted by lexicographical order. +// +// Notably all signatures given should be transformed to "ethereum style" which transforms +// v from 0/1 to 27/28 according to the yellow paper. +func (oracle *CheckpointOracle) RegisterCheckpoint(opts *bind.TransactOpts, index uint64, hash []byte, rnum *big.Int, rhash [32]byte, sigs [][]byte) (*types.Transaction, error) { + var ( + r [][32]byte + s [][32]byte + v []uint8 + ) + for i := 0; i < len(sigs); i++ { + if len(sigs[i]) != 65 { + return nil, errors.New("invalid signature") + } + r = append(r, common.BytesToHash(sigs[i][:32])) + s = append(s, common.BytesToHash(sigs[i][32:64])) + v = append(v, sigs[i][64]) + } + return oracle.contract.SetCheckpoint(opts, rnum, rhash, common.BytesToHash(hash), index, v, r, s) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/block_validator.go b/vendor/github.com/ethereum/go-ethereum/core/block_validator.go index 3b9496fec..b36ca56d7 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/block_validator.go +++ b/vendor/github.com/ethereum/go-ethereum/core/block_validator.go @@ -77,7 +77,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // transition, such as amount of used gas, the receipt roots and the state root // itself. ValidateState returns a database batch if the validation was a success // otherwise nil and an error is returned. -func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { +func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { header := block.Header() if block.GasUsed() != usedGas { return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) diff --git a/vendor/github.com/ethereum/go-ethereum/core/blockchain.go b/vendor/github.com/ethereum/go-ethereum/core/blockchain.go index bd55acf7f..1bf31b239 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/blockchain.go +++ b/vendor/github.com/ethereum/go-ethereum/core/blockchain.go @@ -35,7 +35,6 @@ import ( "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/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -47,34 +46,74 @@ import ( ) var ( + headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil) + headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) + headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) + + accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) + accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) + accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil) + accountCommitTimer = metrics.NewRegisteredTimer("chain/account/commits", nil) + + storageReadTimer = metrics.NewRegisteredTimer("chain/storage/reads", nil) + storageHashTimer = metrics.NewRegisteredTimer("chain/storage/hashes", nil) + storageUpdateTimer = metrics.NewRegisteredTimer("chain/storage/updates", nil) + storageCommitTimer = metrics.NewRegisteredTimer("chain/storage/commits", nil) + blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil) blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil) blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil) blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil) + blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) + blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) - ErrNoGenesis = errors.New("Genesis not found in chain") + blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) + blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) + + errInsertionInterrupted = errors.New("insertion is interrupted") ) const ( bodyCacheLimit = 256 blockCacheLimit = 256 receiptsCacheLimit = 32 + txLookupCacheLimit = 1024 maxFutureBlocks = 256 maxTimeFutureBlocks = 30 badBlockLimit = 10 - triesInMemory = 128 + TriesInMemory = 128 // BlockChainVersion ensures that an incompatible database forces a resync from scratch. - BlockChainVersion uint64 = 3 + // + // Changelog: + // + // - Version 4 + // The following incompatible database changes were added: + // * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted + // * the `Bloom` field of receipt is deleted + // * the `BlockIndex` and `TxIndex` fields of txlookup are deleted + // - Version 5 + // The following incompatible database changes were added: + // * the `TxHash`, `GasCost`, and `ContractAddress` fields are no longer stored for a receipt + // * the `TxHash`, `GasCost`, and `ContractAddress` fields are computed by looking up the + // receipts' corresponding block + // - Version 6 + // The following incompatible database changes were added: + // * Transaction lookup information stores the corresponding block number instead of block hash + // - Version 7 + // The following incompatible database changes were added: + // * Use freezer as the ancient database to maintain all ancient data + BlockChainVersion uint64 = 7 ) // CacheConfig contains the configuration values for the trie caching/pruning // that's resident in a blockchain. type CacheConfig struct { - Disabled bool // Whether to disable trie write caching (archive node) - TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory - TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk - TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk + TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory + TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks + TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk + TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) + TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk } // BlockChain represents the canonical chain given a database with a genesis @@ -105,14 +144,12 @@ type BlockChain struct { chainSideFeed event.Feed chainHeadFeed event.Feed logsFeed event.Feed + blockProcFeed event.Feed scope event.SubscriptionScope genesisBlock *types.Block - mu sync.RWMutex // global mutex for locking chain operations chainmu sync.RWMutex // blockchain insertion lock - procmu sync.RWMutex // block processor lock - checkpoint int // checkpoint counts towards the new checkpoint currentBlock atomic.Value // Current head of the block chain currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) @@ -121,6 +158,7 @@ type BlockChain struct { bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format receiptsCache *lru.Cache // Cache for the most recent receipts per block blockCache *lru.Cache // Cache for the most recent entire blocks + txLookupCache *lru.Cache // Cache for the most recent transaction lookup data. futureBlocks *lru.Cache // future blocks are blocks added for later processing quit chan struct{} // blockchain quit channel @@ -129,13 +167,15 @@ type BlockChain struct { procInterrupt int32 // interrupt signaler for block processing wg sync.WaitGroup // chain processing wait group for shutting down - engine consensus.Engine - processor Processor // block processor interface - validator Validator // block and state validator interface - vmConfig vm.Config + engine consensus.Engine + validator Validator // Block and state validator interface + prefetcher Prefetcher // Block state prefetcher interface + processor Processor // Block transaction processor interface + vmConfig vm.Config - badBlocks *lru.Cache // Bad block cache - shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. + badBlocks *lru.Cache // Bad block cache + shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. + terminateInsert func(common.Hash, uint64) bool // Testing hook used to terminate ancient receipt chain insertion. } // NewBlockChain returns a fully initialised block chain using information @@ -153,6 +193,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) blockCache, _ := lru.New(blockCacheLimit) + txLookupCache, _ := lru.New(txLookupCacheLimit) futureBlocks, _ := lru.New(maxFutureBlocks) badBlocks, _ := lru.New(badBlockLimit) @@ -168,13 +209,15 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par bodyRLPCache: bodyRLPCache, receiptsCache: receiptsCache, blockCache: blockCache, + txLookupCache: txLookupCache, futureBlocks: futureBlocks, engine: engine, vmConfig: vmConfig, badBlocks: badBlocks, } - bc.SetValidator(NewBlockValidator(chainConfig, bc, engine)) - bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine)) + bc.validator = NewBlockValidator(chainConfig, bc, engine) + bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) + bc.processor = NewStateProcessor(chainConfig, bc, engine) var err error bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt) @@ -185,9 +228,51 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par if bc.genesisBlock == nil { return nil, ErrNoGenesis } + // Initialize the chain with ancient data if it isn't empty. + if bc.empty() { + rawdb.InitDatabaseFromFreezer(bc.db) + } if err := bc.loadLastState(); err != nil { return nil, err } + // The first thing the node will do is reconstruct the verification data for + // the head block (ethash cache or clique voting snapshot). Might as well do + // it in advance. + bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true) + + if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 { + var ( + needRewind bool + low uint64 + ) + // The head full block may be rolled back to a very low height due to + // blockchain repair. If the head full block is even lower than the ancient + // chain, truncate the ancient store. + fullBlock := bc.CurrentBlock() + if fullBlock != nil && fullBlock != bc.genesisBlock && fullBlock.NumberU64() < frozen-1 { + needRewind = true + low = fullBlock.NumberU64() + } + // In fast sync, it may happen that ancient data has been written to the + // ancient store, but the LastFastBlock has not been updated, truncate the + // extra data here. + fastBlock := bc.CurrentFastBlock() + if fastBlock != nil && fastBlock.NumberU64() < frozen-1 { + needRewind = true + if fastBlock.NumberU64() < low || low == 0 { + low = fastBlock.NumberU64() + } + } + if needRewind { + var hashes []common.Hash + previous := bc.CurrentHeader().Number.Uint64() + for i := low + 1; i <= bc.CurrentHeader().Number.Uint64(); i++ { + hashes = append(hashes, rawdb.ReadCanonicalHash(bc.db, i)) + } + bc.Rollback(hashes) + log.Warn("Truncate ancient chain", "from", previous, "to", low) + } + } // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain for hash := range BadHashes { if header := bc.GetHeaderByHash(hash); header != nil { @@ -215,6 +300,20 @@ func (bc *BlockChain) GetVMConfig() *vm.Config { return &bc.vmConfig } +// empty returns an indicator whether the blockchain is empty. +// Note, it's a special case that we connect a non-empty ancient +// database with an empty node, so that we can plugin the ancient +// into node seamlessly. +func (bc *BlockChain) empty() bool { + genesis := bc.genesisBlock.Hash() + for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db), rawdb.ReadHeadHeaderHash(bc.db), rawdb.ReadHeadFastBlockHash(bc.db)} { + if hash != genesis { + return false + } + } + return true +} + // loadLastState loads the last known chain state from the database. This method // assumes that the chain manager mutex is held. func (bc *BlockChain) loadLastState() error { @@ -239,9 +338,11 @@ func (bc *BlockChain) loadLastState() error { if err := bc.repair(¤tBlock); err != nil { return err } + rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash()) } // Everything seems to be fine, set as the head block bc.currentBlock.Store(currentBlock) + headBlockGauge.Update(int64(currentBlock.NumberU64())) // Restore the last known head header currentHeader := currentBlock.Header() @@ -254,12 +355,14 @@ func (bc *BlockChain) loadLastState() error { // Restore the last known head fast block bc.currentFastBlock.Store(currentBlock) + headFastBlockGauge.Update(int64(currentBlock.NumberU64())) + if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { if block := bc.GetBlockByHash(head); block != nil { bc.currentFastBlock.Store(block) + headFastBlockGauge.Update(int64(block.NumberU64())) } } - // Issue a status log for the user currentFastBlock := bc.CurrentFastBlock() @@ -281,50 +384,71 @@ func (bc *BlockChain) loadLastState() error { func (bc *BlockChain) SetHead(head uint64) error { log.Warn("Rewinding blockchain", "target", head) - bc.mu.Lock() - defer bc.mu.Unlock() + bc.chainmu.Lock() + defer bc.chainmu.Unlock() + + updateFn := func(db ethdb.KeyValueWriter, header *types.Header) { + // Rewind the block chain, ensuring we don't end up with a stateless head block + if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() < currentBlock.NumberU64() { + newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) + if newHeadBlock == nil { + newHeadBlock = bc.genesisBlock + } else { + if _, err := state.New(newHeadBlock.Root(), bc.stateCache); err != nil { + // Rewound state missing, rolled back to before pivot, reset to genesis + newHeadBlock = bc.genesisBlock + } + } + rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash()) + bc.currentBlock.Store(newHeadBlock) + headBlockGauge.Update(int64(newHeadBlock.NumberU64())) + } + + // Rewind the fast block in a simpleton way to the target head + if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() { + newHeadFastBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) + // If either blocks reached nil, reset to the genesis state + if newHeadFastBlock == nil { + newHeadFastBlock = bc.genesisBlock + } + rawdb.WriteHeadFastBlockHash(db, newHeadFastBlock.Hash()) + bc.currentFastBlock.Store(newHeadFastBlock) + headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) + } + } // Rewind the header chain, deleting all block bodies until then - delFn := func(db rawdb.DatabaseDeleter, hash common.Hash, num uint64) { - rawdb.DeleteBody(db, hash, num) + delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) { + // Ignore the error here since light client won't hit this path + frozen, _ := bc.db.Ancients() + if num+1 <= frozen { + // Truncate all relative data(header, total difficulty, body, receipt + // and canonical hash) from ancient store. + if err := bc.db.TruncateAncients(num + 1); err != nil { + log.Crit("Failed to truncate ancient data", "number", num, "err", err) + } + + // Remove the hash <-> number mapping from the active store. + rawdb.DeleteHeaderNumber(db, hash) + } else { + // Remove relative body and receipts from the active store. + // The header, total difficulty and canonical hash will be + // removed in the hc.SetHead function. + rawdb.DeleteBody(db, hash, num) + rawdb.DeleteReceipts(db, hash, num) + } + // Todo(rjl493456442) txlookup, bloombits, etc } - bc.hc.SetHead(head, delFn) - currentHeader := bc.hc.CurrentHeader() + bc.hc.SetHead(head, updateFn, delFn) // Clear out any stale content from the caches bc.bodyCache.Purge() bc.bodyRLPCache.Purge() bc.receiptsCache.Purge() bc.blockCache.Purge() + bc.txLookupCache.Purge() bc.futureBlocks.Purge() - // Rewind the block chain, ensuring we don't end up with a stateless head block - if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentHeader.Number.Uint64() < currentBlock.NumberU64() { - bc.currentBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())) - } - if currentBlock := bc.CurrentBlock(); currentBlock != nil { - if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil { - // Rewound state missing, rolled back to before pivot, reset to genesis - bc.currentBlock.Store(bc.genesisBlock) - } - } - // Rewind the fast block in a simpleton way to the target head - if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && currentHeader.Number.Uint64() < currentFastBlock.NumberU64() { - bc.currentFastBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())) - } - // If either blocks reached nil, reset to the genesis state - if currentBlock := bc.CurrentBlock(); currentBlock == nil { - bc.currentBlock.Store(bc.genesisBlock) - } - if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock == nil { - bc.currentFastBlock.Store(bc.genesisBlock) - } - currentBlock := bc.CurrentBlock() - currentFastBlock := bc.CurrentFastBlock() - - rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash()) - rawdb.WriteHeadFastBlockHash(bc.db, currentFastBlock.Hash()) - return bc.loadLastState() } @@ -336,13 +460,14 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error { if block == nil { return fmt.Errorf("non existent block [%x…]", hash[:4]) } - if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB(), 0); err != nil { + if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB()); err != nil { return err } // If all checks out, manually set the head block - bc.mu.Lock() + bc.chainmu.Lock() bc.currentBlock.Store(block) - bc.mu.Unlock() + headBlockGauge.Update(int64(block.NumberU64())) + bc.chainmu.Unlock() log.Info("Committed new head block", "number", block.Number(), "hash", hash) return nil @@ -365,31 +490,13 @@ func (bc *BlockChain) CurrentFastBlock() *types.Block { return bc.currentFastBlock.Load().(*types.Block) } -// SetProcessor sets the processor required for making state modifications. -func (bc *BlockChain) SetProcessor(processor Processor) { - bc.procmu.Lock() - defer bc.procmu.Unlock() - bc.processor = processor -} - -// SetValidator sets the validator which is used to validate incoming blocks. -func (bc *BlockChain) SetValidator(validator Validator) { - bc.procmu.Lock() - defer bc.procmu.Unlock() - bc.validator = validator -} - // Validator returns the current validator. func (bc *BlockChain) Validator() Validator { - bc.procmu.RLock() - defer bc.procmu.RUnlock() return bc.validator } // Processor returns the current processor. func (bc *BlockChain) Processor() Processor { - bc.procmu.RLock() - defer bc.procmu.RUnlock() return bc.processor } @@ -420,8 +527,8 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error { if err := bc.SetHead(0); err != nil { return err } - bc.mu.Lock() - defer bc.mu.Unlock() + bc.chainmu.Lock() + defer bc.chainmu.Unlock() // Prepare the genesis block and reinitialise the chain if err := bc.hc.WriteTd(genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil { @@ -432,9 +539,12 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error { bc.genesisBlock = genesis bc.insert(bc.genesisBlock) bc.currentBlock.Store(bc.genesisBlock) + headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) + bc.hc.SetGenesis(bc.genesisBlock.Header()) bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) bc.currentFastBlock.Store(bc.genesisBlock) + headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) return nil } @@ -457,7 +567,7 @@ func (bc *BlockChain) repair(head **types.Block) error { if block == nil { return fmt.Errorf("missing block %d [%x]", (*head).NumberU64()-1, (*head).ParentHash()) } - (*head) = block + *head = block } } @@ -468,8 +578,8 @@ func (bc *BlockChain) Export(w io.Writer) error { // ExportN writes a subset of the active chain to the given writer. func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error { - bc.mu.RLock() - defer bc.mu.RUnlock() + bc.chainmu.RLock() + defer bc.chainmu.RUnlock() if first > last { return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last) @@ -490,7 +600,6 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error { reported = time.Now() } } - return nil } @@ -509,6 +618,7 @@ func (bc *BlockChain) insert(block *types.Block) { rawdb.WriteHeadBlockHash(bc.db, block.Hash()) bc.currentBlock.Store(block) + headBlockGauge.Update(int64(block.NumberU64())) // If the block is better than our head or is on a different chain, force update heads if updateHeads { @@ -516,6 +626,7 @@ func (bc *BlockChain) insert(block *types.Block) { rawdb.WriteHeadFastBlockHash(bc.db, block.Hash()) bc.currentFastBlock.Store(block) + headFastBlockGauge.Update(int64(block.NumberU64())) } } @@ -645,7 +756,10 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { if number == nil { return nil } - receipts := rawdb.ReadReceipts(bc.db, hash, *number) + receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig) + if receipts == nil { + return nil + } bc.receiptsCache.Add(hash, receipts) return receipts } @@ -704,10 +818,10 @@ func (bc *BlockChain) Stop() { // - HEAD: So we don't need to reprocess any blocks in the general case // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle // - HEAD-127: So we have a hard limit on the number of blocks reexecuted - if !bc.cacheConfig.Disabled { + if !bc.cacheConfig.TrieDirtyDisabled { triedb := bc.stateCache.TrieDB() - for _, offset := range []uint64{0, 1, triesInMemory - 1} { + for _, offset := range []uint64{0, 1, TriesInMemory - 1} { if number := bc.CurrentBlock().NumberU64(); number > offset { recent := bc.GetBlockByNumber(number - offset) @@ -756,8 +870,8 @@ const ( // Rollback is designed to remove a chain of links from the database that aren't // certain enough to be valid. func (bc *BlockChain) Rollback(chain []common.Hash) { - bc.mu.Lock() - defer bc.mu.Unlock() + bc.chainmu.Lock() + defer bc.chainmu.Unlock() for i := len(chain) - 1; i >= 0; i-- { hash := chain[i] @@ -768,134 +882,329 @@ func (bc *BlockChain) Rollback(chain []common.Hash) { } if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash { newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1) - bc.currentFastBlock.Store(newFastBlock) rawdb.WriteHeadFastBlockHash(bc.db, newFastBlock.Hash()) + bc.currentFastBlock.Store(newFastBlock) + headFastBlockGauge.Update(int64(newFastBlock.NumberU64())) } if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash { newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1) - bc.currentBlock.Store(newBlock) rawdb.WriteHeadBlockHash(bc.db, newBlock.Hash()) + bc.currentBlock.Store(newBlock) + headBlockGauge.Update(int64(newBlock.NumberU64())) } } + // Truncate ancient data which exceeds the current header. + // + // Notably, it can happen that system crashes without truncating the ancient data + // but the head indicator has been updated in the active store. Regarding this issue, + // system will self recovery by truncating the extra data during the setup phase. + if err := bc.truncateAncient(bc.hc.CurrentHeader().Number.Uint64()); err != nil { + log.Crit("Truncate ancient store failed", "err", err) + } } -// SetReceiptsData computes all the non-consensus fields of the receipts -func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts types.Receipts) error { - signer := types.MakeSigner(config, block.Number()) - - transactions, logIndex := block.Transactions(), uint(0) - if len(transactions) != len(receipts) { - return errors.New("transaction and receipt count mismatch") +// truncateAncient rewinds the blockchain to the specified header and deletes all +// data in the ancient store that exceeds the specified header. +func (bc *BlockChain) truncateAncient(head uint64) error { + frozen, err := bc.db.Ancients() + if err != nil { + return err } - - for j := 0; j < len(receipts); j++ { - // The transaction hash can be retrieved from the transaction itself - receipts[j].TxHash = transactions[j].Hash() - - // The contract address can be derived from the transaction itself - if transactions[j].To() == nil { - // Deriving the signer is expensive, only do if it's actually needed - from, _ := types.Sender(signer, transactions[j]) - receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce()) - } - // The used gas can be calculated based on previous receipts - if j == 0 { - receipts[j].GasUsed = receipts[j].CumulativeGasUsed - } else { - receipts[j].GasUsed = receipts[j].CumulativeGasUsed - receipts[j-1].CumulativeGasUsed - } - // The derived log fields can simply be set from the block and transaction - for k := 0; k < len(receipts[j].Logs); k++ { - receipts[j].Logs[k].BlockNumber = block.NumberU64() - receipts[j].Logs[k].BlockHash = block.Hash() - receipts[j].Logs[k].TxHash = receipts[j].TxHash - receipts[j].Logs[k].TxIndex = uint(j) - receipts[j].Logs[k].Index = logIndex - logIndex++ - } + // Short circuit if there is no data to truncate in ancient store. + if frozen <= head+1 { + return nil } + // Truncate all the data in the freezer beyond the specified head + if err := bc.db.TruncateAncients(head + 1); err != nil { + return err + } + // Clear out any stale content from the caches + bc.hc.headerCache.Purge() + bc.hc.tdCache.Purge() + bc.hc.numberCache.Purge() + + // Clear out any stale content from the caches + bc.bodyCache.Purge() + bc.bodyRLPCache.Purge() + bc.receiptsCache.Purge() + bc.blockCache.Purge() + bc.txLookupCache.Purge() + bc.futureBlocks.Purge() + + log.Info("Rewind ancient data", "number", head) return nil } +// numberHash is just a container for a number and a hash, to represent a block +type numberHash struct { + number uint64 + hash common.Hash +} + // InsertReceiptChain attempts to complete an already existing header chain with // transaction and receipt data. -func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { +func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) { + // We don't require the chainMu here since we want to maximize the + // concurrency of header insertion and receipt insertion. bc.wg.Add(1) defer bc.wg.Done() + var ( + ancientBlocks, liveBlocks types.Blocks + ancientReceipts, liveReceipts []types.Receipts + ) // Do a sanity check that the provided chain is actually ordered and linked - for i := 1; i < len(blockChain); i++ { - if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() { - log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(), - "prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash()) - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(), - blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4]) + for i := 0; i < len(blockChain); i++ { + if i != 0 { + if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() { + log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(), + "prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash()) + return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(), + blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4]) + } + } + if blockChain[i].NumberU64() <= ancientLimit { + ancientBlocks, ancientReceipts = append(ancientBlocks, blockChain[i]), append(ancientReceipts, receiptChain[i]) + } else { + liveBlocks, liveReceipts = append(liveBlocks, blockChain[i]), append(liveReceipts, receiptChain[i]) } } var ( stats = struct{ processed, ignored int32 }{} start = time.Now() - bytes = 0 - batch = bc.db.NewBatch() + size = 0 ) - for i, block := range blockChain { - receipts := receiptChain[i] - // Short circuit insertion if shutting down or processing failed - if atomic.LoadInt32(&bc.procInterrupt) == 1 { - return 0, nil - } - // Short circuit if the owner header is unknown - if !bc.HasHeader(block.Hash(), block.NumberU64()) { - return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) - } - // Skip if the entire data is already known - if bc.HasBlock(block.Hash(), block.NumberU64()) { - stats.ignored++ - continue - } - // Compute all the non-consensus fields of the receipts - if err := SetReceiptsData(bc.chainConfig, block, receipts); err != nil { - return i, fmt.Errorf("failed to set receipts data: %v", err) - } - // Write all the data out into the database - rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()) - rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts) - rawdb.WriteTxLookupEntries(batch, block) + // updateHead updates the head fast sync block if the inserted blocks are better + // and returns a indicator whether the inserted blocks are canonical. + updateHead := func(head *types.Block) bool { + bc.chainmu.Lock() - stats.processed++ - - if batch.ValueSize() >= ethdb.IdealBatchSize { - if err := batch.Write(); err != nil { - return 0, err + // Rewind may have occurred, skip in that case. + if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 { + currentFastBlock, td := bc.CurrentFastBlock(), bc.GetTd(head.Hash(), head.NumberU64()) + if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 { + rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) + bc.currentFastBlock.Store(head) + headFastBlockGauge.Update(int64(head.NumberU64())) + bc.chainmu.Unlock() + return true } - bytes += batch.ValueSize() - batch.Reset() } + bc.chainmu.Unlock() + return false } - if batch.ValueSize() > 0 { - bytes += batch.ValueSize() + // writeAncient writes blockchain and corresponding receipt chain into ancient store. + // + // this function only accepts canonical chain data. All side chain will be reverted + // eventually. + writeAncient := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { + var ( + previous = bc.CurrentFastBlock() + batch = bc.db.NewBatch() + ) + // If any error occurs before updating the head or we are inserting a side chain, + // all the data written this time wll be rolled back. + defer func() { + if previous != nil { + if err := bc.truncateAncient(previous.NumberU64()); err != nil { + log.Crit("Truncate ancient store failed", "err", err) + } + } + }() + var deleted []*numberHash + for i, block := range blockChain { + // Short circuit insertion if shutting down or processing failed + if atomic.LoadInt32(&bc.procInterrupt) == 1 { + return 0, errInsertionInterrupted + } + // Short circuit insertion if it is required(used in testing only) + if bc.terminateInsert != nil && bc.terminateInsert(block.Hash(), block.NumberU64()) { + return i, errors.New("insertion is terminated for testing purpose") + } + // Short circuit if the owner header is unknown + if !bc.HasHeader(block.Hash(), block.NumberU64()) { + return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) + } + var ( + start = time.Now() + logged = time.Now() + count int + ) + // Migrate all ancient blocks. This can happen if someone upgrades from Geth + // 1.8.x to 1.9.x mid-fast-sync. Perhaps we can get rid of this path in the + // long term. + for { + // We can ignore the error here since light client won't hit this code path. + frozen, _ := bc.db.Ancients() + if frozen >= block.NumberU64() { + break + } + h := rawdb.ReadCanonicalHash(bc.db, frozen) + b := rawdb.ReadBlock(bc.db, h, frozen) + size += rawdb.WriteAncientBlock(bc.db, b, rawdb.ReadReceipts(bc.db, h, frozen, bc.chainConfig), rawdb.ReadTd(bc.db, h, frozen)) + count += 1 + + // Always keep genesis block in active database. + if b.NumberU64() != 0 { + deleted = append(deleted, &numberHash{b.NumberU64(), b.Hash()}) + } + if time.Since(logged) > 8*time.Second { + log.Info("Migrating ancient blocks", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + // Don't collect too much in-memory, write it out every 100K blocks + if len(deleted) > 100000 { + + // Sync the ancient store explicitly to ensure all data has been flushed to disk. + if err := bc.db.Sync(); err != nil { + return 0, err + } + // Wipe out canonical block data. + for _, nh := range deleted { + rawdb.DeleteBlockWithoutNumber(batch, nh.hash, nh.number) + rawdb.DeleteCanonicalHash(batch, nh.number) + } + if err := batch.Write(); err != nil { + return 0, err + } + batch.Reset() + // Wipe out side chain too. + for _, nh := range deleted { + for _, hash := range rawdb.ReadAllHashes(bc.db, nh.number) { + rawdb.DeleteBlock(batch, hash, nh.number) + } + } + if err := batch.Write(); err != nil { + return 0, err + } + batch.Reset() + deleted = deleted[0:] + } + } + if count > 0 { + log.Info("Migrated ancient blocks", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + } + // Flush data into ancient database. + size += rawdb.WriteAncientBlock(bc.db, block, receiptChain[i], bc.GetTd(block.Hash(), block.NumberU64())) + rawdb.WriteTxLookupEntries(batch, block) + + stats.processed++ + } + // Flush all tx-lookup index data. + size += batch.ValueSize() if err := batch.Write(); err != nil { return 0, err } - } + batch.Reset() - // Update the head fast sync block if better - bc.mu.Lock() - head := blockChain[len(blockChain)-1] - if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case - currentFastBlock := bc.CurrentFastBlock() - if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 { - rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) - bc.currentFastBlock.Store(head) + // Sync the ancient store explicitly to ensure all data has been flushed to disk. + if err := bc.db.Sync(); err != nil { + return 0, err + } + if !updateHead(blockChain[len(blockChain)-1]) { + return 0, errors.New("side blocks can't be accepted as the ancient chain data") + } + previous = nil // disable rollback explicitly + + // Wipe out canonical block data. + for _, nh := range deleted { + rawdb.DeleteBlockWithoutNumber(batch, nh.hash, nh.number) + rawdb.DeleteCanonicalHash(batch, nh.number) + } + for _, block := range blockChain { + // Always keep genesis block in active database. + if block.NumberU64() != 0 { + rawdb.DeleteBlockWithoutNumber(batch, block.Hash(), block.NumberU64()) + rawdb.DeleteCanonicalHash(batch, block.NumberU64()) + } + } + if err := batch.Write(); err != nil { + return 0, err + } + batch.Reset() + + // Wipe out side chain too. + for _, nh := range deleted { + for _, hash := range rawdb.ReadAllHashes(bc.db, nh.number) { + rawdb.DeleteBlock(batch, hash, nh.number) + } + } + for _, block := range blockChain { + // Always keep genesis block in active database. + if block.NumberU64() != 0 { + for _, hash := range rawdb.ReadAllHashes(bc.db, block.NumberU64()) { + rawdb.DeleteBlock(batch, hash, block.NumberU64()) + } + } + } + if err := batch.Write(); err != nil { + return 0, err + } + return 0, nil + } + // writeLive writes blockchain and corresponding receipt chain into active store. + writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { + batch := bc.db.NewBatch() + for i, block := range blockChain { + // Short circuit insertion if shutting down or processing failed + if atomic.LoadInt32(&bc.procInterrupt) == 1 { + return 0, errInsertionInterrupted + } + // Short circuit if the owner header is unknown + if !bc.HasHeader(block.Hash(), block.NumberU64()) { + return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) + } + if bc.HasBlock(block.Hash(), block.NumberU64()) { + stats.ignored++ + continue + } + // Write all the data out into the database + rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()) + rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i]) + rawdb.WriteTxLookupEntries(batch, block) + + stats.processed++ + if batch.ValueSize() >= ethdb.IdealBatchSize { + if err := batch.Write(); err != nil { + return 0, err + } + size += batch.ValueSize() + batch.Reset() + } + } + if batch.ValueSize() > 0 { + size += batch.ValueSize() + if err := batch.Write(); err != nil { + return 0, err + } + } + updateHead(blockChain[len(blockChain)-1]) + return 0, nil + } + // Write downloaded chain data and corresponding receipt chain data. + if len(ancientBlocks) > 0 { + if n, err := writeAncient(ancientBlocks, ancientReceipts); err != nil { + if err == errInsertionInterrupted { + return 0, nil + } + return n, err + } + } + if len(liveBlocks) > 0 { + if n, err := writeLive(liveBlocks, liveReceipts); err != nil { + if err == errInsertionInterrupted { + return 0, nil + } + return n, err } } - bc.mu.Unlock() + head := blockChain[len(blockChain)-1] context := []interface{}{ "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)), "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)), - "size", common.StorageSize(bytes), + "size", common.StorageSize(size), } if stats.ignored > 0 { context = append(context, []interface{}{"ignored", stats.ignored}...) @@ -907,10 +1216,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ var lastWrite uint64 -// WriteBlockWithoutState writes only the block and its metadata to the database, +// writeBlockWithoutState writes only the block and its metadata to the database, // but does not write any state. This is used to construct competing side forks // up to the point where they exceed the canonical total difficulty. -func (bc *BlockChain) WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) { +func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (err error) { bc.wg.Add(1) defer bc.wg.Done() @@ -922,8 +1231,37 @@ func (bc *BlockChain) WriteBlockWithoutState(block *types.Block, td *big.Int) (e return nil } +// writeKnownBlock updates the head block flag with a known block +// and introduces chain reorg if necessary. +func (bc *BlockChain) writeKnownBlock(block *types.Block) error { + bc.wg.Add(1) + defer bc.wg.Done() + + current := bc.CurrentBlock() + if block.ParentHash() != current.Hash() { + if err := bc.reorg(current, block); err != nil { + return err + } + } + // Write the positional metadata for transaction/receipt lookups. + // Preimages here is empty, ignore it. + rawdb.WriteTxLookupEntries(bc.db, block) + + bc.insert(block) + return nil +} + // WriteBlockWithState writes the block and all associated state to the database. func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) { + bc.chainmu.Lock() + defer bc.chainmu.Unlock() + + return bc.writeBlockWithState(block, receipts, state) +} + +// writeBlockWithState writes the block and all associated state to the database, +// but is expects the chain mutex to be held. +func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) { bc.wg.Add(1) defer bc.wg.Done() @@ -933,9 +1271,6 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. return NonStatTy, consensus.ErrUnknownAncestor } // Make sure no inconsistent state is leaked during insertion - bc.mu.Lock() - defer bc.mu.Unlock() - currentBlock := bc.CurrentBlock() localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) externTd := new(big.Int).Add(block.Difficulty(), ptd) @@ -953,7 +1288,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. triedb := bc.stateCache.TrieDB() // If we're running an archive node, always flush - if bc.cacheConfig.Disabled { + if bc.cacheConfig.TrieDirtyDisabled { if err := triedb.Commit(root, false); err != nil { return NonStatTy, err } @@ -962,7 +1297,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive bc.triegc.Push(root, -int64(block.NumberU64())) - if current := block.NumberU64(); current > triesInMemory { + if current := block.NumberU64(); current > TriesInMemory { // If we exceeded our memory allowance, flush matured singleton nodes to disk var ( nodes, imgs = triedb.Size() @@ -972,7 +1307,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. triedb.Cap(limit - ethdb.IdealBatchSize) } // Find the next state trie we need to commit - chosen := current - triesInMemory + chosen := current - TriesInMemory // If we exceeded out time allowance, flush an entire trie to disk if bc.gcproc > bc.cacheConfig.TrieTimeLimit { @@ -984,8 +1319,8 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. } else { // If we're exceeding limits but haven't reached a large enough memory gap, // warn the user that the system is becoming unstable. - if chosen < lastWrite+triesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit { - log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/triesInMemory) + if chosen < lastWrite+TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit { + log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/TriesInMemory) } // Flush an entire trie and restart the counters triedb.Commit(header.Root, true) @@ -1077,15 +1412,25 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { if len(chain) == 0 { return 0, nil } + + bc.blockProcFeed.Send(true) + defer bc.blockProcFeed.Send(false) + + // Remove already known canon-blocks + var ( + block, prev *types.Block + ) // Do a sanity check that the provided chain is actually ordered and linked for i := 1; i < len(chain); i++ { - if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() { + block = chain[i] + prev = chain[i-1] + if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() { // Chain broke ancestry, log a message (programming error) and skip insertion - log.Error("Non contiguous block insert", "number", chain[i].Number(), "hash", chain[i].Hash(), - "parent", chain[i].ParentHash(), "prevnumber", chain[i-1].Number(), "prevhash", chain[i-1].Hash()) + log.Error("Non contiguous block insert", "number", block.Number(), "hash", block.Hash(), + "parent", block.ParentHash(), "prevnumber", prev.Number(), "prevhash", prev.Hash()) - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, chain[i-1].NumberU64(), - chain[i-1].Hash().Bytes()[:4], i, chain[i].NumberU64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash().Bytes()[:4]) + return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, prev.NumberU64(), + prev.Hash().Bytes()[:4], i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4]) } } // Pre-checks passed, start the full block imports @@ -1099,7 +1444,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { return n, err } -// insertChain is the internal implementation of insertChain, which assumes that +// insertChain is the internal implementation of InsertChain, which assumes that // 1) chains are contiguous, and 2) The chain mutex is held. // // This method is split out so that import batches that require re-injecting @@ -1108,7 +1453,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { // is imported, but then new canon-head is added before the actual sidechain // completes, then the historic state could be pruned again func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []interface{}, []*types.Log, error) { - // If the chain is terminating, don't even bother starting u + // If the chain is terminating, don't even bother starting up if atomic.LoadInt32(&bc.procInterrupt) == 1 { return 0, nil, nil, nil } @@ -1136,17 +1481,61 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] defer close(abort) // Peek the error for the first block to decide the directing import logic - it := newInsertIterator(chain, results, bc.Validator()) + it := newInsertIterator(chain, results, bc.validator) block, err := it.next() + + // Left-trim all the known blocks + if err == ErrKnownBlock { + // First block (and state) is known + // 1. We did a roll-back, and should now do a re-import + // 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot + // from the canonical chain, which has not been verified. + // Skip all known blocks that are behind us + var ( + current = bc.CurrentBlock() + localTd = bc.GetTd(current.Hash(), current.NumberU64()) + externTd = bc.GetTd(block.ParentHash(), block.NumberU64()-1) // The first block can't be nil + ) + for block != nil && err == ErrKnownBlock { + externTd = new(big.Int).Add(externTd, block.Difficulty()) + if localTd.Cmp(externTd) < 0 { + break + } + log.Debug("Ignoring already known block", "number", block.Number(), "hash", block.Hash()) + stats.ignored++ + + block, err = it.next() + } + // The remaining blocks are still known blocks, the only scenario here is: + // During the fast sync, the pivot point is already submitted but rollback + // happens. Then node resets the head full block to a lower height via `rollback` + // and leaves a few known blocks in the database. + // + // When node runs a fast sync again, it can re-import a batch of known blocks via + // `insertChain` while a part of them have higher total difficulty than current + // head full block(new pivot point). + for block != nil && err == ErrKnownBlock { + log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash()) + if err := bc.writeKnownBlock(block); err != nil { + return it.index, nil, nil, err + } + lastCanon = block + + block, err = it.next() + } + // Falls through to the block import + } switch { // First block is pruned, insert as sidechain and reorg only if TD grows enough case err == consensus.ErrPrunedAncestor: - return bc.insertSidechain(block, it) + log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash()) + return bc.insertSideChain(block, it) // First block is future, shove it (and all children) to the future queue (unknown ancestor) case err == consensus.ErrFutureBlock || (err == consensus.ErrUnknownAncestor && bc.futureBlocks.Contains(it.first().ParentHash())): for block != nil && (it.index == 0 || err == consensus.ErrUnknownAncestor) { + log.Debug("Future block, postponing import", "number", block.Number(), "hash", block.Hash()) if err := bc.addFutureBlock(block); err != nil { return it.index, events, coalescedLogs, err } @@ -1158,20 +1547,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] // If there are any still remaining, mark as ignored return it.index, events, coalescedLogs, err - // First block (and state) is known - // 1. We did a roll-back, and should now do a re-import - // 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot - // from the canonical chain, which has not been verified. - case err == ErrKnownBlock: - // Skip all known blocks that behind us - current := bc.CurrentBlock().NumberU64() - - for block != nil && err == ErrKnownBlock && current >= block.NumberU64() { - stats.ignored++ - block, err = it.next() - } - // Falls through to the block import - // Some other error occurred, abort case err != nil: stats.ignored += len(it.chain) @@ -1179,7 +1554,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] return it.index, events, coalescedLogs, err } // No validation errors for the first block (or chain prefix skipped) - for ; block != nil && err == nil; block, err = it.next() { + for ; block != nil && err == nil || err == ErrKnownBlock; block, err = it.next() { // If the chain is terminating, stop processing blocks if atomic.LoadInt32(&bc.procInterrupt) == 1 { log.Debug("Premature abort during blocks processing") @@ -1190,43 +1565,111 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] bc.reportBlock(block, nil, ErrBlacklistedHash) return it.index, events, coalescedLogs, ErrBlacklistedHash } + // If the block is known (in the middle of the chain), it's a special case for + // Clique blocks where they can share state among each other, so importing an + // older block might complete the state of the subsequent one. In this case, + // just skip the block (we already validated it once fully (and crashed), since + // its header and body was already in the database). + if err == ErrKnownBlock { + logger := log.Debug + if bc.chainConfig.Clique == nil { + logger = log.Warn + } + logger("Inserted known block", "number", block.Number(), "hash", block.Hash(), + "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(), + "root", block.Root()) + + if err := bc.writeKnownBlock(block); err != nil { + return it.index, nil, nil, err + } + stats.processed++ + + // We can assume that logs are empty here, since the only way for consecutive + // Clique blocks to have the same state is if there are no transactions. + events = append(events, ChainEvent{block, block.Hash(), nil}) + lastCanon = block + + continue + } // Retrieve the parent block and it's state to execute on top start := time.Now() parent := it.previous() if parent == nil { - parent = bc.GetBlock(block.ParentHash(), block.NumberU64()-1) + parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) } - state, err := state.New(parent.Root(), bc.stateCache) + statedb, err := state.New(parent.Root, bc.stateCache) if err != nil { return it.index, events, coalescedLogs, err } - // Process block using the parent state as reference point. - t0 := time.Now() - receipts, logs, usedGas, err := bc.processor.Process(block, state, bc.vmConfig) - t1 := time.Now() + // If we have a followup block, run that against the current state to pre-cache + // transactions and probabilistically some of the account/storage trie nodes. + var followupInterrupt uint32 + + if !bc.cacheConfig.TrieCleanNoPrefetch { + if followup, err := it.peek(); followup != nil && err == nil { + go func(start time.Time) { + throwaway, _ := state.New(parent.Root, bc.stateCache) + bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) + + blockPrefetchExecuteTimer.Update(time.Since(start)) + if atomic.LoadUint32(&followupInterrupt) == 1 { + blockPrefetchInterruptMeter.Mark(1) + } + }(time.Now()) + } + } + // Process block using the parent state as reference point + substart := time.Now() + receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig) if err != nil { bc.reportBlock(block, receipts, err) + atomic.StoreUint32(&followupInterrupt, 1) return it.index, events, coalescedLogs, err } + // Update the metrics touched during block processing + accountReadTimer.Update(statedb.AccountReads) // Account reads are complete, we can mark them + storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete, we can mark them + accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete, we can mark them + storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete, we can mark them + + triehash := statedb.AccountHashes + statedb.StorageHashes // Save to not double count in validation + trieproc := statedb.AccountReads + statedb.AccountUpdates + trieproc += statedb.StorageReads + statedb.StorageUpdates + + blockExecutionTimer.Update(time.Since(substart) - trieproc - triehash) + // Validate the state using the default validator - if err := bc.Validator().ValidateState(block, parent, state, receipts, usedGas); err != nil { + substart = time.Now() + if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { bc.reportBlock(block, receipts, err) + atomic.StoreUint32(&followupInterrupt, 1) return it.index, events, coalescedLogs, err } - t2 := time.Now() proctime := time.Since(start) + // Update the metrics touched during block validation + accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete, we can mark them + storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete, we can mark them + + blockValidationTimer.Update(time.Since(substart) - (statedb.AccountHashes + statedb.StorageHashes - triehash)) + // Write the block to the chain and get the status. - status, err := bc.WriteBlockWithState(block, receipts, state) - t3 := time.Now() + substart = time.Now() + status, err := bc.writeBlockWithState(block, receipts, statedb) if err != nil { + atomic.StoreUint32(&followupInterrupt, 1) return it.index, events, coalescedLogs, err } + atomic.StoreUint32(&followupInterrupt, 1) + + // Update the metrics touched during block commit + accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them + storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them + + blockWriteTimer.Update(time.Since(substart) - statedb.AccountCommits - statedb.StorageCommits) blockInsertTimer.UpdateSince(start) - blockExecutionTimer.Update(t1.Sub(t0)) - blockValidationTimer.Update(t2.Sub(t1)) - blockWriteTimer.Update(t3.Sub(t2)) + switch status { case CanonStatTy: log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(), @@ -1247,13 +1690,20 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()), "root", block.Root()) events = append(events, ChainSideEvent{block}) + + default: + // This in theory is impossible, but lets be nice to our future selves and leave + // a log, instead of trying to track down blocks imports that don't emit logs. + log.Warn("Inserted block with unknown status", "number", block.Number(), "hash", block.Hash(), + "diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)), + "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()), + "root", block.Root()) } - blockInsertTimer.UpdateSince(start) stats.processed++ stats.usedGas += usedGas - cache, _ := bc.stateCache.TrieDB().Size() - stats.report(chain, it.index, cache) + dirty, _ := bc.stateCache.TrieDB().Size() + stats.report(chain, it.index, dirty) } // Any blocks remaining here? The only ones we care about are the future ones if block != nil && err == consensus.ErrFutureBlock { @@ -1278,16 +1728,16 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] return it.index, events, coalescedLogs, err } -// insertSidechain is called when an import batch hits upon a pruned ancestor +// insertSideChain is called when an import batch hits upon a pruned ancestor // error, which happens when a sidechain with a sufficiently old fork-block is // found. // // The method writes all (header-and-body-valid) blocks to disk, then tries to // switch over to the new chain if the TD exceeded the current chain. -func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (int, []interface{}, []*types.Log, error) { +func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, []interface{}, []*types.Log, error) { var ( externTd *big.Int - current = bc.CurrentBlock().NumberU64() + current = bc.CurrentBlock() ) // The first sidechain block error is already verified to be ErrPrunedAncestor. // Since we don't import them here, we expect ErrUnknownAncestor for the remaining @@ -1296,8 +1746,18 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i err := consensus.ErrPrunedAncestor for ; block != nil && (err == consensus.ErrPrunedAncestor); block, err = it.next() { // Check the canonical state root for that number - if number := block.NumberU64(); current >= number { - if canonical := bc.GetBlockByNumber(number); canonical != nil && canonical.Root() == block.Root() { + if number := block.NumberU64(); current.NumberU64() >= number { + canonical := bc.GetBlockByNumber(number) + if canonical != nil && canonical.Hash() == block.Hash() { + // Not a sidechain block, this is a re-import of a canon block which has it's state pruned + + // Collect the TD of the block. Since we know it's a canon one, + // we can get it directly, and not (like further below) use + // the parent and then add the block on top + externTd = bc.GetTd(block.Hash(), block.NumberU64()) + continue + } + if canonical != nil && canonical.Root() == block.Root() { // This is most likely a shadow-state attack. When a fork is imported into the // database, and it eventually reaches a block height which is not pruned, we // just found that the state already exist! This means that the sidechain block @@ -1320,7 +1780,7 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i if !bc.HasBlock(block.Hash(), block.NumberU64()) { start := time.Now() - if err := bc.WriteBlockWithoutState(block, externTd); err != nil { + if err := bc.writeBlockWithoutState(block, externTd); err != nil { return it.index, nil, nil, err } log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(), @@ -1335,9 +1795,9 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i // // If the externTd was larger than our local TD, we now need to reimport the previous // blocks to regenerate the required state - localTd := bc.GetTd(bc.CurrentBlock().Hash(), current) + localTd := bc.GetTd(current.Hash(), current.NumberU64()) if localTd.Cmp(externTd) > 0 { - log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().NumberU64(), "sidetd", externTd, "localtd", localTd) + log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd) return it.index, nil, nil, err } // Gather all the sidechain hashes (full blocks may be memory heavy) @@ -1345,7 +1805,7 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i hashes []common.Hash numbers []uint64 ) - parent := bc.GetHeader(it.previous().Hash(), it.previous().NumberU64()) + parent := it.previous() for parent != nil && !bc.HasState(parent.Root) { hashes = append(hashes, parent.Hash()) numbers = append(numbers, parent.Number.Uint64()) @@ -1414,7 +1874,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { if number == nil { return } - receipts := rawdb.ReadReceipts(bc.db, hash, *number) + receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig) for _, receipt := range receipts { for _, log := range receipt.Logs { l := *log @@ -1475,24 +1935,28 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } // Ensure the user sees large reorgs if len(oldChain) > 0 && len(newChain) > 0 { - logFn := log.Debug + logFn := log.Info + msg := "Chain reorg detected" if len(oldChain) > 63 { + msg = "Large chain reorg detected" logFn = log.Warn } - logFn("Chain split detected", "number", commonBlock.Number(), "hash", commonBlock.Hash(), + logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(), "drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash()) + blockReorgAddMeter.Mark(int64(len(newChain))) + blockReorgDropMeter.Mark(int64(len(oldChain))) } else { log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash()) } - // Insert the new chain, taking care of the proper incremental order - for i := len(newChain) - 1; i >= 0; i-- { + // Insert the new chain(except the head block(reverse order)), + // taking care of the proper incremental order. + for i := len(newChain) - 1; i >= 1; i-- { // Insert the block in the canonical way, re-writing history bc.insert(newChain[i]) - // Collect reborn logs due to chain reorg (except head block (reverse order)) - if i != 0 { - collectLogs(newChain[i].Hash(), false) - } + // Collect reborn logs due to chain reorg + collectLogs(newChain[i].Hash(), false) + // Write lookup entries for hash based transaction/receipt searches rawdb.WriteTxLookupEntries(bc.db, newChain[i]) addedTxs = append(addedTxs, newChain[i].Transactions()...) @@ -1503,8 +1967,16 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { for _, tx := range types.TxDifference(deletedTxs, addedTxs) { rawdb.DeleteTxLookupEntry(batch, tx.Hash()) } + // Delete any canonical number assignments above the new head + number := bc.CurrentBlock().NumberU64() + for i := number + 1; ; i++ { + hash := rawdb.ReadCanonicalHash(bc.db, i) + if hash == (common.Hash{}) { + break + } + rawdb.DeleteCanonicalHash(batch, i) + } batch.Write() - // If any logs need to be fired, do it now. In theory we could avoid creating // this goroutine if there are no events to fire, but realistcally that only // ever happens if we're reorging empty blocks, which will only happen on idle @@ -1625,36 +2097,12 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (i defer bc.wg.Done() whFunc := func(header *types.Header) error { - bc.mu.Lock() - defer bc.mu.Unlock() - _, err := bc.hc.WriteHeader(header) return err } - return bc.hc.InsertHeaderChain(chain, whFunc, start) } -// writeHeader writes a header into the local chain, given that its parent is -// already known. If the total difficulty of the newly inserted header becomes -// greater than the current known TD, the canonical chain is re-routed. -// -// Note: This method is not concurrent-safe with inserting blocks simultaneously -// into the chain, as side effects caused by reorganisations cannot be emulated -// without the real blocks. Hence, writing headers directly should only be done -// in two scenarios: pure-header mode of operation (light clients), or properly -// separated header/block phases (non-archive clients). -func (bc *BlockChain) writeHeader(header *types.Header) error { - bc.wg.Add(1) - defer bc.wg.Done() - - bc.mu.Lock() - defer bc.mu.Unlock() - - _, err := bc.hc.WriteHeader(header) - return err -} - // CurrentHeader retrieves the current head header of the canonical chain. The // header is retrieved from the HeaderChain's internal cache. func (bc *BlockChain) CurrentHeader() *types.Header { @@ -1703,9 +2151,6 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com // // Note: ancestor == 0 returns the same block, 1 returns its parent and so on. func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - bc.chainmu.Lock() - defer bc.chainmu.Unlock() - return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) } @@ -1715,7 +2160,23 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { return bc.hc.GetHeaderByNumber(number) } -// Config retrieves the blockchain's chain configuration. +// GetTransactionLookup retrieves the lookup associate with the given transaction +// hash from the cache or database. +func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry { + // Short circuit if the txlookup already in the cache, retrieve otherwise + if lookup, exist := bc.txLookupCache.Get(hash); exist { + return lookup.(*rawdb.LegacyTxLookupEntry) + } + tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) + if tx == nil { + return nil + } + lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} + bc.txLookupCache.Add(hash, lookup) + return lookup +} + +// Config retrieves the chain's fork configuration. func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } // Engine retrieves the blockchain's consensus engine. @@ -1745,3 +2206,9 @@ func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Su func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { return bc.scope.Track(bc.logsFeed.Subscribe(ch)) } + +// SubscribeBlockProcessingEvent registers a subscription of bool where true means +// block processing has started while false means it has stopped. +func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { + return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/blockchain_insert.go b/vendor/github.com/ethereum/go-ethereum/core/blockchain_insert.go index ff668925a..5685b0a4b 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/blockchain_insert.go +++ b/vendor/github.com/ethereum/go-ethereum/core/blockchain_insert.go @@ -39,7 +39,7 @@ const statsReportLimit = 8 * time.Second // report prints statistics if some number of blocks have been processed // or more than a few seconds have passed since the last message. -func (st *insertStats) report(chain []*types.Block, index int, cache common.StorageSize) { +func (st *insertStats) report(chain []*types.Block, index int, dirty common.StorageSize) { // Fetch the timings for the batch var ( now = mclock.Now() @@ -63,7 +63,7 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) } - context = append(context, []interface{}{"cache", cache}...) + context = append(context, []interface{}{"dirty", dirty}...) if st.queued > 0 { context = append(context, []interface{}{"queued", st.queued}...) @@ -80,10 +80,13 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor // insertIterator is a helper to assist during chain import. type insertIterator struct { - chain types.Blocks - results <-chan error - index int - validator Validator + chain types.Blocks // Chain of blocks being iterated over + + results <-chan error // Verification result sink from the consensus engine + errors []error // Header verification errors for the blocks + + index int // Current offset of the iterator + validator Validator // Validator to run if verification succeeds } // newInsertIterator creates a new iterator based on the given blocks, which are @@ -92,6 +95,7 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid return &insertIterator{ chain: chain, results: results, + errors: make([]error, 0, len(chain)), index: -1, validator: validator, } @@ -100,23 +104,50 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid // next returns the next block in the iterator, along with any potential validation // error for that block. When the end is reached, it will return (nil, nil). func (it *insertIterator) next() (*types.Block, error) { + // If we reached the end of the chain, abort if it.index+1 >= len(it.chain) { it.index = len(it.chain) return nil, nil } + // Advance the iterator and wait for verification result if not yet done it.index++ - if err := <-it.results; err != nil { - return it.chain[it.index], err + if len(it.errors) <= it.index { + it.errors = append(it.errors, <-it.results) } + if it.errors[it.index] != nil { + return it.chain[it.index], it.errors[it.index] + } + // Block header valid, run body validation and return return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index]) } -// previous returns the previous block was being processed, or nil -func (it *insertIterator) previous() *types.Block { +// peek returns the next block in the iterator, along with any potential validation +// error for that block, but does **not** advance the iterator. +// +// Both header and body validation errors (nil too) is cached into the iterator +// to avoid duplicating work on the following next() call. +func (it *insertIterator) peek() (*types.Block, error) { + // If we reached the end of the chain, abort + if it.index+1 >= len(it.chain) { + return nil, nil + } + // Wait for verification result if not yet done + if len(it.errors) <= it.index+1 { + it.errors = append(it.errors, <-it.results) + } + if it.errors[it.index+1] != nil { + return it.chain[it.index+1], it.errors[it.index+1] + } + // Block header valid, ignore body validation since we don't have a parent anyway + return it.chain[it.index+1], nil +} + +// previous returns the previous header that was being processed, or nil. +func (it *insertIterator) previous() *types.Header { if it.index < 1 { return nil } - return it.chain[it.index-1] + return it.chain[it.index-1].Header() } // first returns the first block in the it. diff --git a/vendor/github.com/ethereum/go-ethereum/core/chain_indexer.go b/vendor/github.com/ethereum/go-ethereum/core/chain_indexer.go index 1adde1fcb..c0c2c4f7f 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/chain_indexer.go +++ b/vendor/github.com/ethereum/go-ethereum/core/chain_indexer.go @@ -97,7 +97,7 @@ type ChainIndexer struct { // NewChainIndexer creates a new chain indexer to do background processing on // chain segments of a given size after certain number of confirmations passed. // The throttling parameter might be used to prevent database thrashing. -func NewChainIndexer(chainDb, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer { +func NewChainIndexer(chainDb ethdb.Database, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer { c := &ChainIndexer{ chainDb: chainDb, indexDb: indexDb, @@ -128,12 +128,13 @@ func (c *ChainIndexer) AddCheckpoint(section uint64, shead common.Hash) { c.lock.Lock() defer c.lock.Unlock() + // Short circuit if the given checkpoint is below than local's. + if c.checkpointSections >= section+1 || section < c.storedSections { + return + } c.checkpointSections = section + 1 c.checkpointHead = shead - if section < c.storedSections { - return - } c.setSectionHead(section, shead) c.setValidSections(section + 1) } @@ -243,7 +244,7 @@ func (c *ChainIndexer) newHead(head uint64, reorg bool) { // If a reorg happened, invalidate all sections until that point if reorg { // Revert the known section number to the reorg point - known := head / c.sectionSize + known := (head + 1) / c.sectionSize stored := known if known < c.checkpointSections { known = 0 @@ -323,6 +324,7 @@ func (c *ChainIndexer) updateLoop() { updated = time.Now() } // Cache the current section count and head to allow unlocking the mutex + c.verifyLastHead() section := c.storedSections var oldHead common.Hash if section > 0 { @@ -342,8 +344,8 @@ func (c *ChainIndexer) updateLoop() { } c.lock.Lock() - // If processing succeeded and no reorgs occcurred, mark the section completed - if err == nil && oldHead == c.SectionHead(section-1) { + // If processing succeeded and no reorgs occurred, mark the section completed + if err == nil && (section == 0 || oldHead == c.SectionHead(section-1)) { c.setSectionHead(section, newHead) c.setValidSections(section + 1) if c.storedSections == c.knownSections && updating { @@ -358,6 +360,7 @@ func (c *ChainIndexer) updateLoop() { } else { // If processing failed, don't retry until further notification c.log.Debug("Chain index processing failed", "section", section, "err", err) + c.verifyLastHead() c.knownSections = c.storedSections } } @@ -411,6 +414,18 @@ func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (com return lastHead, nil } +// verifyLastHead compares last stored section head with the corresponding block hash in the +// actual canonical chain and rolls back reorged sections if necessary to ensure that stored +// sections are all valid +func (c *ChainIndexer) verifyLastHead() { + for c.storedSections > 0 && c.storedSections > c.checkpointSections { + if c.SectionHead(c.storedSections-1) == rawdb.ReadCanonicalHash(c.chainDb, c.storedSections*c.sectionSize-1) { + return + } + c.setValidSections(c.storedSections - 1) + } +} + // Sections returns the number of processed sections maintained by the indexer // and also the information about the last header indexed for potential canonical // verifications. @@ -418,6 +433,7 @@ func (c *ChainIndexer) Sections() (uint64, uint64, common.Hash) { c.lock.Lock() defer c.lock.Unlock() + c.verifyLastHead() return c.storedSections, c.storedSections*c.sectionSize - 1, c.SectionHead(c.storedSections - 1) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go index d563d85ee..0b0fcdb4a 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go +++ b/vendor/github.com/ethereum/go-ethereum/core/chain_makers.go @@ -71,6 +71,13 @@ func (b *BlockGen) SetNonce(nonce types.BlockNonce) { b.header.Nonce = nonce } +// SetDifficulty sets the difficulty field of the generated block. This method is +// useful for Clique tests where the difficulty does not depend on time. For the +// ethash tests, please use OffsetTime, which implicitly recalculates the diff. +func (b *BlockGen) SetDifficulty(diff *big.Int) { + b.header.Difficulty = diff +} + // AddTx adds a transaction to the generated block. If no coinbase has // been set, the block's coinbase is set to the zero address. // @@ -96,7 +103,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.SetCoinbase(common.Address{}) } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) + receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) if err != nil { panic(err) } @@ -104,6 +111,15 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.receipts = append(b.receipts, receipt) } +// AddUncheckedTx forcefully adds a transaction to the block without any +// validation. +// +// AddUncheckedTx will cause consensus failures when used during real +// chain processing. This is best used in conjunction with raw block insertion. +func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) { + b.txs = append(b.txs, tx) +} + // Number returns the block number of the block being generated. func (b *BlockGen) Number() *big.Int { return new(big.Int).Set(b.header.Number) @@ -197,7 +213,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } if b.engine != nil { // Finalize and seal the block - block, _ := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts) + block, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts) // Write state changes to db root, err := statedb.Commit(config.IsEIP158(b.header.Number)) diff --git a/vendor/github.com/ethereum/go-ethereum/core/error.go b/vendor/github.com/ethereum/go-ethereum/core/error.go index 410eca1e1..cd4be3d70 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/error.go +++ b/vendor/github.com/ethereum/go-ethereum/core/error.go @@ -32,4 +32,7 @@ var ( // ErrNonceTooHigh is returned if the nonce of a transaction is higher than the // next one expected based on the local chain. ErrNonceTooHigh = errors.New("nonce too high") + + // ErrNoGenesis is returned when there is no Genesis Block. + ErrNoGenesis = errors.New("genesis not found in chain") ) diff --git a/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go b/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go new file mode 100644 index 000000000..8c1700879 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/forkid/forkid.go @@ -0,0 +1,236 @@ +// Copyright 2019 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 forkid implements EIP-2124 (https://eips.ethereum.org/EIPS/eip-2124). +package forkid + +import ( + "encoding/binary" + "errors" + "hash/crc32" + "math" + "math/big" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +var ( + // ErrRemoteStale is returned by the validator if a remote fork checksum is a + // subset of our already applied forks, but the announced next fork block is + // not on our already passed chain. + ErrRemoteStale = errors.New("remote needs update") + + // ErrLocalIncompatibleOrStale is returned by the validator if a remote fork + // checksum does not match any local checksum variation, signalling that the + // two chains have diverged in the past at some point (possibly at genesis). + ErrLocalIncompatibleOrStale = errors.New("local incompatible or needs update") +) + +// ID is a fork identifier as defined by EIP-2124. +type ID struct { + Hash [4]byte // CRC32 checksum of the genesis block and passed fork block numbers + Next uint64 // Block number of the next upcoming fork, or 0 if no forks are known +} + +// NewID calculates the Ethereum fork ID from the chain config and head. +func NewID(chain *core.BlockChain) ID { + return newID( + chain.Config(), + chain.Genesis().Hash(), + chain.CurrentHeader().Number.Uint64(), + ) +} + +// newID is the internal version of NewID, which takes extracted values as its +// arguments instead of a chain. The reason is to allow testing the IDs without +// having to simulate an entire blockchain. +func newID(config *params.ChainConfig, genesis common.Hash, head uint64) ID { + // Calculate the starting checksum from the genesis hash + hash := crc32.ChecksumIEEE(genesis[:]) + + // Calculate the current fork checksum and the next fork block + var next uint64 + for _, fork := range gatherForks(config) { + if fork <= head { + // Fork already passed, checksum the previous hash and the fork number + hash = checksumUpdate(hash, fork) + continue + } + next = fork + break + } + return ID{Hash: checksumToBytes(hash), Next: next} +} + +// NewFilter creates an filter that returns if a fork ID should be rejected or not +// based on the local chain's status. +func NewFilter(chain *core.BlockChain) func(id ID) error { + return newFilter( + chain.Config(), + chain.Genesis().Hash(), + func() uint64 { + return chain.CurrentHeader().Number.Uint64() + }, + ) +} + +// newFilter is the internal version of NewFilter, taking closures as its arguments +// instead of a chain. The reason is to allow testing it without having to simulate +// an entire blockchain. +func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() uint64) func(id ID) error { + // Calculate the all the valid fork hash and fork next combos + var ( + forks = gatherForks(config) + sums = make([][4]byte, len(forks)+1) // 0th is the genesis + ) + hash := crc32.ChecksumIEEE(genesis[:]) + sums[0] = checksumToBytes(hash) + for i, fork := range forks { + hash = checksumUpdate(hash, fork) + sums[i+1] = checksumToBytes(hash) + } + // Add two sentries to simplify the fork checks and don't require special + // casing the last one. + forks = append(forks, math.MaxUint64) // Last fork will never be passed + + // Create a validator that will filter out incompatible chains + return func(id ID) error { + // Run the fork checksum validation ruleset: + // 1. If local and remote FORK_CSUM matches, connect. + // The two nodes are in the same fork state currently. They might know + // of differing future forks, but that's not relevant until the fork + // triggers (might be postponed, nodes might be updated to match). + // 2. If the remote FORK_CSUM is a subset of the local past forks and the + // remote FORK_NEXT matches with the locally following fork block number, + // connect. + // Remote node is currently syncing. It might eventually diverge from + // us, but at this current point in time we don't have enough information. + // 3. If the remote FORK_CSUM is a superset of the local past forks and can + // be completed with locally known future forks, connect. + // Local node is currently syncing. It might eventually diverge from + // the remote, but at this current point in time we don't have enough + // information. + // 4. Reject in all other cases. + head := headfn() + for i, fork := range forks { + // If our head is beyond this fork, continue to the next (we have a dummy + // fork of maxuint64 as the last item to always fail this check eventually). + if head > fork { + continue + } + // Found the first unpassed fork block, check if our current state matches + // the remote checksum (rule #1). + if sums[i] == id.Hash { + // Yay, fork checksum matched, ignore any upcoming fork + return nil + } + // The local and remote nodes are in different forks currently, check if the + // remote checksum is a subset of our local forks (rule #2). + for j := 0; j < i; j++ { + if sums[j] == id.Hash { + // Remote checksum is a subset, validate based on the announced next fork + if forks[j] != id.Next { + return ErrRemoteStale + } + return nil + } + } + // Remote chain is not a subset of our local one, check if it's a superset by + // any chance, signalling that we're simply out of sync (rule #3). + for j := i + 1; j < len(sums); j++ { + if sums[j] == id.Hash { + // Yay, remote checksum is a superset, ignore upcoming forks + return nil + } + } + // No exact, subset or superset match. We are on differing chains, reject. + return ErrLocalIncompatibleOrStale + } + log.Error("Impossible fork ID validation", "id", id) + return nil // Something's very wrong, accept rather than reject + } +} + +// checksum calculates the IEEE CRC32 checksum of a block number. +func checksum(fork uint64) uint32 { + var blob [8]byte + binary.BigEndian.PutUint64(blob[:], fork) + return crc32.ChecksumIEEE(blob[:]) +} + +// checksumUpdate calculates the next IEEE CRC32 checksum based on the previous +// one and a fork block number (equivalent to CRC32(original-blob || fork)). +func checksumUpdate(hash uint32, fork uint64) uint32 { + var blob [8]byte + binary.BigEndian.PutUint64(blob[:], fork) + return crc32.Update(hash, crc32.IEEETable, blob[:]) +} + +// checksumToBytes converts a uint32 checksum into a [4]byte array. +func checksumToBytes(hash uint32) [4]byte { + var blob [4]byte + binary.BigEndian.PutUint32(blob[:], hash) + return blob +} + +// gatherForks gathers all the known forks and creates a sorted list out of them. +func gatherForks(config *params.ChainConfig) []uint64 { + // Gather all the fork block numbers via reflection + kind := reflect.TypeOf(params.ChainConfig{}) + conf := reflect.ValueOf(config).Elem() + + var forks []uint64 + for i := 0; i < kind.NumField(); i++ { + // Fetch the next field and skip non-fork rules + field := kind.Field(i) + if !strings.HasSuffix(field.Name, "Block") { + continue + } + if field.Type != reflect.TypeOf(new(big.Int)) { + continue + } + // Extract the fork rule block number and aggregate it + rule := conf.Field(i).Interface().(*big.Int) + if rule != nil { + forks = append(forks, rule.Uint64()) + } + } + // Sort the fork block numbers to permit chronologival XOR + for i := 0; i < len(forks); i++ { + for j := i + 1; j < len(forks); j++ { + if forks[i] > forks[j] { + forks[i], forks[j] = forks[j], forks[i] + } + } + } + // Deduplicate block numbers applying multiple forks + for i := 1; i < len(forks); i++ { + if forks[i] == forks[i-1] { + forks = append(forks[:i], forks[i+1:]...) + i-- + } + } + // Skip any forks in block 0, that's the genesis ruleset + if len(forks) > 0 && forks[0] == 0 { + forks = forks[1:] + } + return forks +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/genesis.go b/vendor/github.com/ethereum/go-ethereum/core/genesis.go index 0d16c0468..8261c18cc 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/genesis.go +++ b/vendor/github.com/ethereum/go-ethereum/core/genesis.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -134,7 +135,7 @@ type GenesisMismatchError struct { } func (e *GenesisMismatchError) Error() string { - return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8]) + return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) } // SetupGenesisBlock writes or updates the genesis block in db. @@ -153,7 +154,8 @@ func (e *GenesisMismatchError) Error() string { func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { return SetupGenesisBlockWithOverride(db, genesis, nil) } -func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constantinopleOverride *big.Int) (*params.ChainConfig, common.Hash, error) { + +func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideIstanbul *big.Int) (*params.ChainConfig, common.Hash, error) { if genesis != nil && genesis.Config == nil { return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig } @@ -167,7 +169,29 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constant log.Info("Writing custom genesis block") } block, err := genesis.Commit(db) - return genesis.Config, block.Hash(), err + if err != nil { + return genesis.Config, common.Hash{}, err + } + return genesis.Config, block.Hash(), nil + } + + // We have the genesis block in database(perhaps in ancient database) + // but the corresponding state is missing. + header := rawdb.ReadHeader(db, stored, 0) + if _, err := state.New(header.Root, state.NewDatabaseWithCache(db, 0)); err != nil { + if genesis == nil { + genesis = DefaultGenesisBlock() + } + // Ensure the stored genesis matches with the given one. + hash := genesis.ToBlock(nil).Hash() + if hash != stored { + return genesis.Config, hash, &GenesisMismatchError{stored, hash} + } + block, err := genesis.Commit(db) + if err != nil { + return genesis.Config, hash, err + } + return genesis.Config, block.Hash(), nil } // Check whether the genesis block is already written. @@ -180,9 +204,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constant // Get the existing chain configuration. newcfg := genesis.configOrDefault(stored) - if constantinopleOverride != nil { - newcfg.ConstantinopleBlock = constantinopleOverride - newcfg.PetersburgBlock = constantinopleOverride + if overrideIstanbul != nil { + newcfg.IstanbulBlock = overrideIstanbul } storedcfg := rawdb.ReadChainConfig(db, stored) if storedcfg == nil { @@ -228,7 +251,7 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { // to the given database (or discards it if nil). func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { if db == nil { - db = ethdb.NewMemDatabase() + db = rawdb.NewMemoryDatabase() } statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) for addr, account := range g.Alloc { @@ -277,6 +300,7 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) rawdb.WriteHeadBlockHash(db, block.Hash()) + rawdb.WriteHeadFastBlockHash(db, block.Hash()) rawdb.WriteHeadHeaderHash(db, block.Hash()) config := g.Config @@ -361,7 +385,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { // Assemble and return the genesis with the precompiles and faucet pre-funded return &Genesis{ Config: &config, - ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...), + ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), GasLimit: 6283185, Difficulty: big.NewInt(1), Alloc: map[common.Address]GenesisAccount{ diff --git a/vendor/github.com/ethereum/go-ethereum/core/headerchain.go b/vendor/github.com/ethereum/go-ethereum/core/headerchain.go index 86a9b9922..a2faa3303 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/headerchain.go +++ b/vendor/github.com/ethereum/go-ethereum/core/headerchain.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" - "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru" ) const ( @@ -104,6 +104,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c } } hc.currentHeaderHash = hc.CurrentHeader().Hash() + headHeaderGauge.Update(hc.CurrentHeader().Number.Int64()) return hc, nil } @@ -185,12 +186,12 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er hc.currentHeaderHash = hash hc.currentHeader.Store(types.CopyHeader(header)) + headHeaderGauge.Update(header.Number.Int64()) status = CanonStatTy } else { status = SideStatTy } - hc.headerCache.Add(hash, header) hc.numberCache.Add(hash, number) @@ -274,9 +275,14 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCa return i, errors.New("aborted") } // If the header's already known, skip it, otherwise store - if hc.HasHeader(header.Hash(), header.Number.Uint64()) { - stats.ignored++ - continue + hash := header.Hash() + if hc.HasHeader(hash, header.Number.Uint64()) { + externTd := hc.GetTd(hash, header.Number.Uint64()) + localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64()) + if externTd == nil || externTd.Cmp(localTd) <= 0 { + stats.ignored++ + continue + } } if err := writeHeader(header); err != nil { return i, err @@ -343,8 +349,11 @@ func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, ma } for ancestor != 0 { if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { - number -= ancestor - return rawdb.ReadCanonicalHash(hc.chainDb, number), number + ancestorHash := rawdb.ReadCanonicalHash(hc.chainDb, number-ancestor) + if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { + number -= ancestor + return ancestorHash, number + } } if *maxNonCanonical == 0 { return common.Hash{}, 0 @@ -451,35 +460,60 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { hc.currentHeader.Store(head) hc.currentHeaderHash = head.Hash() + headHeaderGauge.Update(head.Number.Int64()) } -// DeleteCallback is a callback function that is called by SetHead before -// each header is deleted. -type DeleteCallback func(rawdb.DatabaseDeleter, common.Hash, uint64) +type ( + // UpdateHeadBlocksCallback is a callback function that is called by SetHead + // before head header is updated. + UpdateHeadBlocksCallback func(ethdb.KeyValueWriter, *types.Header) + + // DeleteBlockContentCallback is a callback function that is called by SetHead + // before each header is deleted. + DeleteBlockContentCallback func(ethdb.KeyValueWriter, common.Hash, uint64) +) // SetHead rewinds the local chain to a new head. Everything above the new head // will be deleted and the new one set. -func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) { - height := uint64(0) - - if hdr := hc.CurrentHeader(); hdr != nil { - height = hdr.Number.Uint64() - } - batch := hc.chainDb.NewBatch() +func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) { + var ( + parentHash common.Hash + batch = hc.chainDb.NewBatch() + ) for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() { - hash := hdr.Hash() - num := hdr.Number.Uint64() + hash, num := hdr.Hash(), hdr.Number.Uint64() + + // Rewind block chain to new head. + parent := hc.GetHeader(hdr.ParentHash, num-1) + if parent == nil { + parent = hc.genesisHeader + } + parentHash = hdr.ParentHash + // Notably, since geth has the possibility for setting the head to a low + // height which is even lower than ancient head. + // In order to ensure that the head is always no higher than the data in + // the database(ancient store or active store), we need to update head + // first then remove the relative data from the database. + // + // Update head first(head fast block, head full block) before deleting the data. + if updateFn != nil { + updateFn(hc.chainDb, parent) + } + // Update head header then. + rawdb.WriteHeadHeaderHash(hc.chainDb, parentHash) + + // Remove the relative data from the database. if delFn != nil { delFn(batch, hash, num) } + // Rewind header chain to new head. rawdb.DeleteHeader(batch, hash, num) rawdb.DeleteTd(batch, hash, num) + rawdb.DeleteCanonicalHash(batch, num) - hc.currentHeader.Store(hc.GetHeader(hdr.ParentHash, hdr.Number.Uint64()-1)) - } - // Roll back the canonical chain numbering - for i := height; i > head; i-- { - rawdb.DeleteCanonicalHash(batch, i) + hc.currentHeader.Store(parent) + hc.currentHeaderHash = parentHash + headHeaderGauge.Update(parent.Number.Int64()) } batch.Write() @@ -487,13 +521,6 @@ func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) { hc.headerCache.Purge() hc.tdCache.Purge() hc.numberCache.Purge() - - if hc.CurrentHeader() == nil { - hc.currentHeader.Store(hc.genesisHeader) - } - hc.currentHeaderHash = hc.CurrentHeader().Hash() - - rawdb.WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash) } // SetGenesis sets a new genesis block header for the chain diff --git a/vendor/github.com/ethereum/go-ethereum/core/mkalloc.go b/vendor/github.com/ethereum/go-ethereum/core/mkalloc.go index 565e8c582..5118a4fcb 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/mkalloc.go +++ b/vendor/github.com/ethereum/go-ethereum/core/mkalloc.go @@ -52,7 +52,8 @@ func makelist(g *core.Genesis) allocList { if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 { panic(fmt.Sprintf("can't encode account %x", addr)) } - a = append(a, allocItem{addr.Big(), account.Balance}) + bigAddr := new(big.Int).SetBytes(addr.Bytes()) + a = append(a, allocItem{bigAddr, account.Balance}) } sort.Sort(a) return a diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go index 491a125c6..fab7ca56c 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_chain.go @@ -23,13 +23,25 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) // ReadCanonicalHash retrieves the hash assigned to a canonical block number. -func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash { - data, _ := db.Get(headerHashKey(number)) +func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { + data, _ := db.Ancient(freezerHashTable, number) + if len(data) == 0 { + data, _ = db.Get(headerHashKey(number)) + // In the background freezer is moving data from leveldb to flatten files. + // So during the first check for ancient db, the data is not yet in there, + // but when we reach into leveldb, the data was already moved. That would + // result in a not found error. + if len(data) == 0 { + data, _ = db.Ancient(freezerHashTable, number) + } + } if len(data) == 0 { return common.Hash{} } @@ -37,21 +49,38 @@ func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash { } // WriteCanonicalHash stores the hash assigned to a canonical block number. -func WriteCanonicalHash(db DatabaseWriter, hash common.Hash, number uint64) { +func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { log.Crit("Failed to store number to hash mapping", "err", err) } } // DeleteCanonicalHash removes the number to hash canonical mapping. -func DeleteCanonicalHash(db DatabaseDeleter, number uint64) { +func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) { if err := db.Delete(headerHashKey(number)); err != nil { log.Crit("Failed to delete number to hash mapping", "err", err) } } +// ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights, +// both canonical and reorged forks included. +func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash { + prefix := headerKeyPrefix(number) + + hashes := make([]common.Hash, 0, 1) + it := db.NewIteratorWithPrefix(prefix) + defer it.Release() + + for it.Next() { + if key := it.Key(); len(key) == len(prefix)+32 { + hashes = append(hashes, common.BytesToHash(key[len(key)-32:])) + } + } + return hashes +} + // ReadHeaderNumber returns the header number assigned to a hash. -func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 { +func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { data, _ := db.Get(headerNumberKey(hash)) if len(data) != 8 { return nil @@ -60,8 +89,24 @@ func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 { return &number } +// WriteHeaderNumber stores the hash->number mapping. +func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + key := headerNumberKey(hash) + enc := encodeBlockNumber(number) + if err := db.Put(key, enc); err != nil { + log.Crit("Failed to store hash to number mapping", "err", err) + } +} + +// DeleteHeaderNumber removes hash->number mapping. +func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { + if err := db.Delete(headerNumberKey(hash)); err != nil { + log.Crit("Failed to delete hash to number mapping", "err", err) + } +} + // ReadHeadHeaderHash retrieves the hash of the current canonical head header. -func ReadHeadHeaderHash(db DatabaseReader) common.Hash { +func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { data, _ := db.Get(headHeaderKey) if len(data) == 0 { return common.Hash{} @@ -70,14 +115,14 @@ func ReadHeadHeaderHash(db DatabaseReader) common.Hash { } // WriteHeadHeaderHash stores the hash of the current canonical head header. -func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) { +func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { log.Crit("Failed to store last header's hash", "err", err) } } // ReadHeadBlockHash retrieves the hash of the current canonical head block. -func ReadHeadBlockHash(db DatabaseReader) common.Hash { +func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { data, _ := db.Get(headBlockKey) if len(data) == 0 { return common.Hash{} @@ -86,14 +131,14 @@ func ReadHeadBlockHash(db DatabaseReader) common.Hash { } // WriteHeadBlockHash stores the head block's hash. -func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) { +func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { if err := db.Put(headBlockKey, hash.Bytes()); err != nil { log.Crit("Failed to store last block's hash", "err", err) } } // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. -func ReadHeadFastBlockHash(db DatabaseReader) common.Hash { +func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash { data, _ := db.Get(headFastBlockKey) if len(data) == 0 { return common.Hash{} @@ -102,7 +147,7 @@ func ReadHeadFastBlockHash(db DatabaseReader) common.Hash { } // WriteHeadFastBlockHash stores the hash of the current fast-sync head block. -func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) { +func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { log.Crit("Failed to store last fast block's hash", "err", err) } @@ -110,7 +155,7 @@ func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) { // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow // reporting correct numbers across restarts. -func ReadFastTrieProgress(db DatabaseReader) uint64 { +func ReadFastTrieProgress(db ethdb.KeyValueReader) uint64 { data, _ := db.Get(fastTrieProgressKey) if len(data) == 0 { return 0 @@ -120,20 +165,33 @@ func ReadFastTrieProgress(db DatabaseReader) uint64 { // WriteFastTrieProgress stores the fast sync trie process counter to support // retrieving it across restarts. -func WriteFastTrieProgress(db DatabaseWriter, count uint64) { +func WriteFastTrieProgress(db ethdb.KeyValueWriter, count uint64) { if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { log.Crit("Failed to store fast sync trie progress", "err", err) } } // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. -func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { - data, _ := db.Get(headerKey(number, hash)) +func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Ancient(freezerHeaderTable, number) + if len(data) == 0 { + data, _ = db.Get(headerKey(number, hash)) + // In the background freezer is moving data from leveldb to flatten files. + // So during the first check for ancient db, the data is not yet in there, + // but when we reach into leveldb, the data was already moved. That would + // result in a not found error. + if len(data) == 0 { + data, _ = db.Ancient(freezerHeaderTable, number) + } + } return data } // HasHeader verifies the existence of a block header corresponding to the hash. -func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool { +func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { + return true + } if has, err := db.Has(headerKey(number, hash)); !has || err != nil { return false } @@ -141,7 +199,7 @@ func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool { } // ReadHeader retrieves the block header corresponding to the hash. -func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header { +func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { data := ReadHeaderRLP(db, hash, number) if len(data) == 0 { return nil @@ -156,53 +214,69 @@ func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Heade // WriteHeader stores a block header into the database and also stores the hash- // to-number mapping. -func WriteHeader(db DatabaseWriter, header *types.Header) { - // Write the hash -> number mapping +func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { var ( - hash = header.Hash() - number = header.Number.Uint64() - encoded = encodeBlockNumber(number) + hash = header.Hash() + number = header.Number.Uint64() ) - key := headerNumberKey(hash) - if err := db.Put(key, encoded); err != nil { - log.Crit("Failed to store hash to number mapping", "err", err) - } + // Write the hash -> number mapping + WriteHeaderNumber(db, hash, number) + // Write the encoded header data, err := rlp.EncodeToBytes(header) if err != nil { log.Crit("Failed to RLP encode header", "err", err) } - key = headerKey(number, hash) + key := headerKey(number, hash) if err := db.Put(key, data); err != nil { log.Crit("Failed to store header", "err", err) } } // DeleteHeader removes all block header data associated with a hash. -func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) { - if err := db.Delete(headerKey(number, hash)); err != nil { - log.Crit("Failed to delete header", "err", err) - } +func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + deleteHeaderWithoutNumber(db, hash, number) if err := db.Delete(headerNumberKey(hash)); err != nil { log.Crit("Failed to delete hash to number mapping", "err", err) } } +// deleteHeaderWithoutNumber removes only the block header but does not remove +// the hash to number mapping. +func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + if err := db.Delete(headerKey(number, hash)); err != nil { + log.Crit("Failed to delete header", "err", err) + } +} + // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. -func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { - data, _ := db.Get(blockBodyKey(number, hash)) +func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Ancient(freezerBodiesTable, number) + if len(data) == 0 { + data, _ = db.Get(blockBodyKey(number, hash)) + // In the background freezer is moving data from leveldb to flatten files. + // So during the first check for ancient db, the data is not yet in there, + // but when we reach into leveldb, the data was already moved. That would + // result in a not found error. + if len(data) == 0 { + data, _ = db.Ancient(freezerBodiesTable, number) + } + } return data } // WriteBodyRLP stores an RLP encoded block body into the database. -func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { +func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { log.Crit("Failed to store block body", "err", err) } } // HasBody verifies the existence of a block body corresponding to the hash. -func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool { +func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { + return true + } if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { return false } @@ -210,7 +284,7 @@ func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool { } // ReadBody retrieves the block body corresponding to the hash. -func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body { +func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { data := ReadBodyRLP(db, hash, number) if len(data) == 0 { return nil @@ -223,8 +297,8 @@ func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body { return body } -// WriteBody storea a block body into the database. -func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) { +// WriteBody stores a block body into the database. +func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { data, err := rlp.EncodeToBytes(body) if err != nil { log.Crit("Failed to RLP encode body", "err", err) @@ -233,15 +307,31 @@ func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.B } // DeleteBody removes all block body data associated with a hash. -func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) { +func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { if err := db.Delete(blockBodyKey(number, hash)); err != nil { log.Crit("Failed to delete block body", "err", err) } } +// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. +func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Ancient(freezerDifficultyTable, number) + if len(data) == 0 { + data, _ = db.Get(headerTDKey(number, hash)) + // In the background freezer is moving data from leveldb to flatten files. + // So during the first check for ancient db, the data is not yet in there, + // but when we reach into leveldb, the data was already moved. That would + // result in a not found error. + if len(data) == 0 { + data, _ = db.Ancient(freezerDifficultyTable, number) + } + } + return data +} + // ReadTd retrieves a block's total difficulty corresponding to the hash. -func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { - data, _ := db.Get(headerTDKey(number, hash)) +func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { + data := ReadTdRLP(db, hash, number) if len(data) == 0 { return nil } @@ -254,7 +344,7 @@ func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { } // WriteTd stores the total difficulty of a block into the database. -func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) { +func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) { data, err := rlp.EncodeToBytes(td) if err != nil { log.Crit("Failed to RLP encode block total difficulty", "err", err) @@ -265,7 +355,7 @@ func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) { } // DeleteTd removes all block total difficulty data associated with a hash. -func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { +func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { if err := db.Delete(headerTDKey(number, hash)); err != nil { log.Crit("Failed to delete block total difficulty", "err", err) } @@ -273,17 +363,38 @@ func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { // HasReceipts verifies the existence of all the transaction receipts belonging // to a block. -func HasReceipts(db DatabaseReader, hash common.Hash, number uint64) bool { +func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { + if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { + return true + } if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { return false } return true } -// ReadReceipts retrieves all the transaction receipts belonging to a block. -func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts { +// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. +func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Ancient(freezerReceiptTable, number) + if len(data) == 0 { + data, _ = db.Get(blockReceiptsKey(number, hash)) + // In the background freezer is moving data from leveldb to flatten files. + // So during the first check for ancient db, the data is not yet in there, + // but when we reach into leveldb, the data was already moved. That would + // result in a not found error. + if len(data) == 0 { + data, _ = db.Ancient(freezerReceiptTable, number) + } + } + return data +} + +// ReadRawReceipts retrieves all the transaction receipts belonging to a block. +// The receipt metadata fields are not guaranteed to be populated, so they +// should not be used. Use ReadReceipts instead if the metadata is needed. +func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { // Retrieve the flattened receipt slice - data, _ := db.Get(blockReceiptsKey(number, hash)) + data := ReadReceiptsRLP(db, hash, number) if len(data) == 0 { return nil } @@ -294,14 +405,39 @@ func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Rece return nil } receipts := make(types.Receipts, len(storageReceipts)) - for i, receipt := range storageReceipts { - receipts[i] = (*types.Receipt)(receipt) + for i, storageReceipt := range storageReceipts { + receipts[i] = (*types.Receipt)(storageReceipt) + } + return receipts +} + +// ReadReceipts retrieves all the transaction receipts belonging to a block, including +// its correspoinding metadata fields. If it is unable to populate these metadata +// fields then nil is returned. +// +// The current implementation populates these metadata fields by reading the receipts' +// corresponding block body, so if the block body is not found it will return nil even +// if the receipt itself is stored. +func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts { + // We're deriving many fields from the block body, retrieve beside the receipt + receipts := ReadRawReceipts(db, hash, number) + if receipts == nil { + return nil + } + body := ReadBody(db, hash, number) + if body == nil { + log.Error("Missing body but have receipt", "hash", hash, "number", number) + return nil + } + if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { + log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) + return nil } return receipts } // WriteReceipts stores all the transaction receipts belonging to a block. -func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) { +func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { // Convert the receipts into their storage form and serialize them storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) for i, receipt := range receipts { @@ -318,7 +454,7 @@ func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts } // DeleteReceipts removes all receipt data associated with a block hash. -func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { +func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { log.Crit("Failed to delete block receipts", "err", err) } @@ -330,7 +466,7 @@ func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { // // Note, due to concurrent download of header and block body the header and thus // canonical hash can be stored in the database but the body data not (yet). -func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block { +func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { header := ReadHeader(db, hash, number) if header == nil { return nil @@ -343,21 +479,61 @@ func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block } // WriteBlock serializes a block into the database, header and body separately. -func WriteBlock(db DatabaseWriter, block *types.Block) { +func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) WriteHeader(db, block.Header()) } +// WriteAncientBlock writes entire block data into ancient store and returns the total written size. +func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int { + // Encode all block components to RLP format. + headerBlob, err := rlp.EncodeToBytes(block.Header()) + if err != nil { + log.Crit("Failed to RLP encode block header", "err", err) + } + bodyBlob, err := rlp.EncodeToBytes(block.Body()) + if err != nil { + log.Crit("Failed to RLP encode body", "err", err) + } + storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) + for i, receipt := range receipts { + storageReceipts[i] = (*types.ReceiptForStorage)(receipt) + } + receiptBlob, err := rlp.EncodeToBytes(storageReceipts) + if err != nil { + log.Crit("Failed to RLP encode block receipts", "err", err) + } + tdBlob, err := rlp.EncodeToBytes(td) + if err != nil { + log.Crit("Failed to RLP encode block total difficulty", "err", err) + } + // Write all blob to flatten files. + err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob) + if err != nil { + log.Crit("Failed to write block data to ancient store", "err", err) + } + return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(tdBlob) + common.HashLength +} + // DeleteBlock removes all block data associated with a hash. -func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) { +func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { DeleteReceipts(db, hash, number) DeleteHeader(db, hash, number) DeleteBody(db, hash, number) DeleteTd(db, hash, number) } +// DeleteBlockWithoutNumber removes all block data associated with a hash, except +// the hash to number mapping. +func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + DeleteReceipts(db, hash, number) + deleteHeaderWithoutNumber(db, hash, number) + DeleteBody(db, hash, number) + DeleteTd(db, hash, number) +} + // FindCommonAncestor returns the last common ancestor of two block headers -func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header { +func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) if a == nil { diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go index 4ff7e5bd3..38f8fe10e 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_indexes.go @@ -17,90 +17,114 @@ package rawdb import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) // ReadTxLookupEntry retrieves the positional metadata associated with a transaction // hash to allow retrieving the transaction or receipt by hash. -func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) { +func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 { data, _ := db.Get(txLookupKey(hash)) if len(data) == 0 { - return common.Hash{}, 0, 0 + return nil } - var entry TxLookupEntry + // Database v6 tx lookup just stores the block number + if len(data) < common.HashLength { + number := new(big.Int).SetBytes(data).Uint64() + return &number + } + // Database v4-v5 tx lookup format just stores the hash + if len(data) == common.HashLength { + return ReadHeaderNumber(db, common.BytesToHash(data)) + } + // Finally try database v3 tx lookup format + var entry LegacyTxLookupEntry if err := rlp.DecodeBytes(data, &entry); err != nil { - log.Error("Invalid transaction lookup entry RLP", "hash", hash, "err", err) - return common.Hash{}, 0, 0 + log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) + return nil } - return entry.BlockHash, entry.BlockIndex, entry.Index + return &entry.BlockIndex } // WriteTxLookupEntries stores a positional metadata for every transaction from // a block, enabling hash based transaction and receipt lookups. -func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { - for i, tx := range block.Transactions() { - entry := TxLookupEntry{ - BlockHash: block.Hash(), - BlockIndex: block.NumberU64(), - Index: uint64(i), - } - data, err := rlp.EncodeToBytes(entry) - if err != nil { - log.Crit("Failed to encode transaction lookup entry", "err", err) - } - if err := db.Put(txLookupKey(tx.Hash()), data); err != nil { +func WriteTxLookupEntries(db ethdb.KeyValueWriter, block *types.Block) { + number := block.Number().Bytes() + for _, tx := range block.Transactions() { + if err := db.Put(txLookupKey(tx.Hash()), number); err != nil { log.Crit("Failed to store transaction lookup entry", "err", err) } } } // DeleteTxLookupEntry removes all transaction data associated with a hash. -func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { +func DeleteTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash) { db.Delete(txLookupKey(hash)) } // ReadTransaction retrieves a specific transaction from the database, along with // its added positional metadata. -func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { - blockHash, blockNumber, txIndex := ReadTxLookupEntry(db, hash) +func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { + blockNumber := ReadTxLookupEntry(db, hash) + if blockNumber == nil { + return nil, common.Hash{}, 0, 0 + } + blockHash := ReadCanonicalHash(db, *blockNumber) if blockHash == (common.Hash{}) { return nil, common.Hash{}, 0, 0 } - body := ReadBody(db, blockHash, blockNumber) - if body == nil || len(body.Transactions) <= int(txIndex) { - log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex) + body := ReadBody(db, blockHash, *blockNumber) + if body == nil { + log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash) return nil, common.Hash{}, 0, 0 } - return body.Transactions[txIndex], blockHash, blockNumber, txIndex + for txIndex, tx := range body.Transactions { + if tx.Hash() == hash { + return tx, blockHash, *blockNumber, uint64(txIndex) + } + } + log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 } // ReadReceipt retrieves a specific transaction receipt from the database, along with // its added positional metadata. -func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { - blockHash, blockNumber, receiptIndex := ReadTxLookupEntry(db, hash) +func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { + // Retrieve the context of the receipt based on the transaction hash + blockNumber := ReadTxLookupEntry(db, hash) + if blockNumber == nil { + return nil, common.Hash{}, 0, 0 + } + blockHash := ReadCanonicalHash(db, *blockNumber) if blockHash == (common.Hash{}) { return nil, common.Hash{}, 0, 0 } - receipts := ReadReceipts(db, blockHash, blockNumber) - if len(receipts) <= int(receiptIndex) { - log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex) - return nil, common.Hash{}, 0, 0 + // Read all the receipts from the block and return the one with the matching hash + receipts := ReadReceipts(db, blockHash, *blockNumber, config) + for receiptIndex, receipt := range receipts { + if receipt.TxHash == hash { + return receipt, blockHash, *blockNumber, uint64(receiptIndex) + } } - return receipts[receiptIndex], blockHash, blockNumber, receiptIndex + log.Error("Receipt not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 } // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given // section and bit index from the. -func ReadBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) ([]byte, error) { +func ReadBloomBits(db ethdb.KeyValueReader, bit uint, section uint64, head common.Hash) ([]byte, error) { return db.Get(bloomBitsKey(bit, section, head)) } // WriteBloomBits stores the compressed bloom bits vector belonging to the given // section and bit index. -func WriteBloomBits(db DatabaseWriter, bit uint, section uint64, head common.Hash, bits []byte) { +func WriteBloomBits(db ethdb.KeyValueWriter, bit uint, section uint64, head common.Hash, bits []byte) { if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { log.Crit("Failed to store bloom bits", "err", err) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go index 82e4bf045..f8d09fbdd 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/accessors_metadata.go @@ -20,13 +20,14 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) // ReadDatabaseVersion retrieves the version number of the database. -func ReadDatabaseVersion(db DatabaseReader) *uint64 { +func ReadDatabaseVersion(db ethdb.KeyValueReader) *uint64 { var version uint64 enc, _ := db.Get(databaseVerisionKey) @@ -41,7 +42,7 @@ func ReadDatabaseVersion(db DatabaseReader) *uint64 { } // WriteDatabaseVersion stores the version number of the database -func WriteDatabaseVersion(db DatabaseWriter, version uint64) { +func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) { enc, err := rlp.EncodeToBytes(version) if err != nil { log.Crit("Failed to encode database version", "err", err) @@ -52,7 +53,7 @@ func WriteDatabaseVersion(db DatabaseWriter, version uint64) { } // ReadChainConfig retrieves the consensus settings based on the given genesis hash. -func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig { +func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) *params.ChainConfig { data, _ := db.Get(configKey(hash)) if len(data) == 0 { return nil @@ -66,7 +67,7 @@ func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig { } // WriteChainConfig writes the chain config settings to the database. -func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConfig) { +func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.ChainConfig) { if cfg == nil { return } @@ -80,13 +81,13 @@ func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConf } // ReadPreimage retrieves a single preimage of the provided hash. -func ReadPreimage(db DatabaseReader, hash common.Hash) []byte { +func ReadPreimage(db ethdb.KeyValueReader, hash common.Hash) []byte { data, _ := db.Get(preimageKey(hash)) return data } // WritePreimages writes the provided set of preimages to the database. -func WritePreimages(db DatabaseWriter, preimages map[common.Hash][]byte) { +func WritePreimages(db ethdb.KeyValueWriter, preimages map[common.Hash][]byte) { for hash, preimage := range preimages { if err := db.Put(preimageKey(hash), preimage); err != nil { log.Crit("Failed to store trie preimage", "err", err) diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go new file mode 100644 index 000000000..353b7dce6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/database.go @@ -0,0 +1,355 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "bytes" + "errors" + "fmt" + "os" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/leveldb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" + "github.com/olekukonko/tablewriter" +) + +// freezerdb is a database wrapper that enabled freezer data retrievals. +type freezerdb struct { + ethdb.KeyValueStore + ethdb.AncientStore +} + +// Close implements io.Closer, closing both the fast key-value store as well as +// the slow ancient tables. +func (frdb *freezerdb) Close() error { + var errs []error + if err := frdb.KeyValueStore.Close(); err != nil { + errs = append(errs, err) + } + if err := frdb.AncientStore.Close(); err != nil { + errs = append(errs, err) + } + if len(errs) != 0 { + return fmt.Errorf("%v", errs) + } + return nil +} + +// nofreezedb is a database wrapper that disables freezer data retrievals. +type nofreezedb struct { + ethdb.KeyValueStore +} + +// HasAncient returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) HasAncient(kind string, number uint64) (bool, error) { + return false, errNotSupported +} + +// Ancient returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) { + return nil, errNotSupported +} + +// Ancients returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) Ancients() (uint64, error) { + return 0, errNotSupported +} + +// AncientSize returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) AncientSize(kind string) (uint64, error) { + return 0, errNotSupported +} + +// AppendAncient returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error { + return errNotSupported +} + +// TruncateAncients returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) TruncateAncients(items uint64) error { + return errNotSupported +} + +// Sync returns an error as we don't have a backing chain freezer. +func (db *nofreezedb) Sync() error { + return errNotSupported +} + +// NewDatabase creates a high level database on top of a given key-value data +// store without a freezer moving immutable chain segments into cold storage. +func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { + return &nofreezedb{ + KeyValueStore: db, + } +} + +// NewDatabaseWithFreezer creates a high level database on top of a given key- +// value data store with a freezer moving immutable chain segments into cold +// storage. +func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string) (ethdb.Database, error) { + // Create the idle freezer instance + frdb, err := newFreezer(freezer, namespace) + if err != nil { + return nil, err + } + // Since the freezer can be stored separately from the user's key-value database, + // there's a fairly high probability that the user requests invalid combinations + // of the freezer and database. Ensure that we don't shoot ourselves in the foot + // by serving up conflicting data, leading to both datastores getting corrupted. + // + // - If both the freezer and key-value store is empty (no genesis), we just + // initialized a new empty freezer, so everything's fine. + // - If the key-value store is empty, but the freezer is not, we need to make + // sure the user's genesis matches the freezer. That will be checked in the + // blockchain, since we don't have the genesis block here (nor should we at + // this point care, the key-value/freezer combo is valid). + // - If neither the key-value store nor the freezer is empty, cross validate + // the genesis hashes to make sure they are compatible. If they are, also + // ensure that there's no gap between the freezer and sunsequently leveldb. + // - If the key-value store is not empty, but the freezer is we might just be + // upgrading to the freezer release, or we might have had a small chain and + // not frozen anything yet. Ensure that no blocks are missing yet from the + // key-value store, since that would mean we already had an old freezer. + + // If the genesis hash is empty, we have a new key-value store, so nothing to + // validate in this method. If, however, the genesis hash is not nil, compare + // it to the freezer content. + if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 { + if frozen, _ := frdb.Ancients(); frozen > 0 { + // If the freezer already contains something, ensure that the genesis blocks + // match, otherwise we might mix up freezers across chains and destroy both + // the freezer and the key-value store. + if frgenesis, _ := frdb.Ancient(freezerHashTable, 0); !bytes.Equal(kvgenesis, frgenesis) { + return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis) + } + // Key-value store and freezer belong to the same network. Ensure that they + // are contiguous, otherwise we might end up with a non-functional freezer. + if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 { + // Subsequent header after the freezer limit is missing from the database. + // Reject startup is the database has a more recent head. + if *ReadHeaderNumber(db, ReadHeadHeaderHash(db)) > frozen-1 { + return nil, fmt.Errorf("gap (#%d) in the chain between ancients and leveldb", frozen) + } + // Database contains only older data than the freezer, this happens if the + // state was wiped and reinited from an existing freezer. + } else { + // Key-value store continues where the freezer left off, all is fine. We might + // have duplicate blocks (crash after freezer write but before kay-value store + // deletion, but that's fine). + } + } else { + // If the freezer is empty, ensure nothing was moved yet from the key-value + // store, otherwise we'll end up missing data. We check block #1 to decide + // if we froze anything previously or not, but do take care of databases with + // only the genesis block. + if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) { + // Key-value store contains more data than the genesis block, make sure we + // didn't freeze anything yet. + if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { + return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") + } + // Block #1 is still in the database, we're allowed to init a new feezer + } else { + // The head header is still the genesis, we're allowed to init a new feezer + } + } + } + // Freezer is consistent with the key-value database, permit combining the two + go frdb.freeze(db) + + return &freezerdb{ + KeyValueStore: db, + AncientStore: frdb, + }, nil +} + +// NewMemoryDatabase creates an ephemeral in-memory key-value database without a +// freezer moving immutable chain segments into cold storage. +func NewMemoryDatabase() ethdb.Database { + return NewDatabase(memorydb.New()) +} + +// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database +// with an initial starting capacity, but without a freezer moving immutable +// chain segments into cold storage. +func NewMemoryDatabaseWithCap(size int) ethdb.Database { + return NewDatabase(memorydb.NewWithCap(size)) +} + +// NewLevelDBDatabase creates a persistent key-value database without a freezer +// moving immutable chain segments into cold storage. +func NewLevelDBDatabase(file string, cache int, handles int, namespace string) (ethdb.Database, error) { + db, err := leveldb.New(file, cache, handles, namespace) + if err != nil { + return nil, err + } + return NewDatabase(db), nil +} + +// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a +// freezer moving immutable chain segments into cold storage. +func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string) (ethdb.Database, error) { + kvdb, err := leveldb.New(file, cache, handles, namespace) + if err != nil { + return nil, err + } + frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace) + if err != nil { + kvdb.Close() + return nil, err + } + return frdb, nil +} + +// InspectDatabase traverses the entire database and checks the size +// of all different categories of data. +func InspectDatabase(db ethdb.Database) error { + it := db.NewIterator() + defer it.Release() + + var ( + count int64 + start = time.Now() + logged = time.Now() + + // Key-value store statistics + total common.StorageSize + headerSize common.StorageSize + bodySize common.StorageSize + receiptSize common.StorageSize + tdSize common.StorageSize + numHashPairing common.StorageSize + hashNumPairing common.StorageSize + trieSize common.StorageSize + txlookupSize common.StorageSize + preimageSize common.StorageSize + bloomBitsSize common.StorageSize + cliqueSnapsSize common.StorageSize + + // Ancient store statistics + ancientHeaders common.StorageSize + ancientBodies common.StorageSize + ancientReceipts common.StorageSize + ancientHashes common.StorageSize + ancientTds common.StorageSize + + // Les statistic + chtTrieNodes common.StorageSize + bloomTrieNodes common.StorageSize + + // Meta- and unaccounted data + metadata common.StorageSize + unaccounted common.StorageSize + ) + // Inspect key-value database first. + for it.Next() { + var ( + key = it.Key() + size = common.StorageSize(len(key) + len(it.Value())) + ) + total += size + switch { + case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerTDSuffix): + tdSize += size + case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix): + numHashPairing += size + case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength): + headerSize += size + case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength): + hashNumPairing += size + case bytes.HasPrefix(key, blockBodyPrefix) && len(key) == (len(blockBodyPrefix)+8+common.HashLength): + bodySize += size + case bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength): + receiptSize += size + case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength): + txlookupSize += size + case bytes.HasPrefix(key, preimagePrefix) && len(key) == (len(preimagePrefix)+common.HashLength): + preimageSize += size + case bytes.HasPrefix(key, bloomBitsPrefix) && len(key) == (len(bloomBitsPrefix)+10+common.HashLength): + bloomBitsSize += size + case bytes.HasPrefix(key, []byte("clique-")) && len(key) == 7+common.HashLength: + cliqueSnapsSize += size + case bytes.HasPrefix(key, []byte("cht-")) && len(key) == 4+common.HashLength: + chtTrieNodes += size + case bytes.HasPrefix(key, []byte("blt-")) && len(key) == 4+common.HashLength: + bloomTrieNodes += size + case len(key) == common.HashLength: + trieSize += size + default: + var accounted bool + for _, meta := range [][]byte{databaseVerisionKey, headHeaderKey, headBlockKey, headFastBlockKey, fastTrieProgressKey} { + if bytes.Equal(key, meta) { + metadata += size + accounted = true + break + } + } + if !accounted { + unaccounted += size + } + } + count += 1 + if count%1000 == 0 && time.Since(logged) > 8*time.Second { + log.Info("Inspecting database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + // Inspect append-only file store then. + ancients := []*common.StorageSize{&ancientHeaders, &ancientBodies, &ancientReceipts, &ancientHashes, &ancientTds} + for i, category := range []string{freezerHeaderTable, freezerBodiesTable, freezerReceiptTable, freezerHashTable, freezerDifficultyTable} { + if size, err := db.AncientSize(category); err == nil { + *ancients[i] += common.StorageSize(size) + total += common.StorageSize(size) + } + } + // Display the database statistic. + stats := [][]string{ + {"Key-Value store", "Headers", headerSize.String()}, + {"Key-Value store", "Bodies", bodySize.String()}, + {"Key-Value store", "Receipts", receiptSize.String()}, + {"Key-Value store", "Difficulties", tdSize.String()}, + {"Key-Value store", "Block number->hash", numHashPairing.String()}, + {"Key-Value store", "Block hash->number", hashNumPairing.String()}, + {"Key-Value store", "Transaction index", txlookupSize.String()}, + {"Key-Value store", "Bloombit index", bloomBitsSize.String()}, + {"Key-Value store", "Trie nodes", trieSize.String()}, + {"Key-Value store", "Trie preimages", preimageSize.String()}, + {"Key-Value store", "Clique snapshots", cliqueSnapsSize.String()}, + {"Key-Value store", "Singleton metadata", metadata.String()}, + {"Ancient store", "Headers", ancientHeaders.String()}, + {"Ancient store", "Bodies", ancientBodies.String()}, + {"Ancient store", "Receipts", ancientReceipts.String()}, + {"Ancient store", "Difficulties", ancientTds.String()}, + {"Ancient store", "Block number->hash", ancientHashes.String()}, + {"Light client", "CHT trie nodes", chtTrieNodes.String()}, + {"Light client", "Bloom trie nodes", bloomTrieNodes.String()}, + } + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Database", "Category", "Size"}) + table.SetFooter([]string{"", "Total", total.String()}) + table.AppendBulk(stats) + table.Render() + + if unaccounted > 0 { + log.Error("Database contains unaccounted data", "size", unaccounted) + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go new file mode 100644 index 000000000..5497c59d4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer.go @@ -0,0 +1,393 @@ +// Copyright 2019 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 rawdb + +import ( + "errors" + "fmt" + "math" + "os" + "path/filepath" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/params" + "github.com/prometheus/tsdb/fileutil" +) + +var ( + // errUnknownTable is returned if the user attempts to read from a table that is + // not tracked by the freezer. + errUnknownTable = errors.New("unknown table") + + // errOutOrderInsertion is returned if the user attempts to inject out-of-order + // binary blobs into the freezer. + errOutOrderInsertion = errors.New("the append operation is out-order") + + // errSymlinkDatadir is returned if the ancient directory specified by user + // is a symbolic link. + errSymlinkDatadir = errors.New("symbolic link datadir is not supported") +) + +const ( + // freezerRecheckInterval is the frequency to check the key-value database for + // chain progression that might permit new blocks to be frozen into immutable + // storage. + freezerRecheckInterval = time.Minute + + // freezerBatchLimit is the maximum number of blocks to freeze in one batch + // before doing an fsync and deleting it from the key-value store. + freezerBatchLimit = 30000 +) + +// freezer is an memory mapped append-only database to store immutable chain data +// into flat files: +// +// - The append only nature ensures that disk writes are minimized. +// - The memory mapping ensures we can max out system memory for caching without +// reserving it for go-ethereum. This would also reduce the memory requirements +// of Geth, and thus also GC overhead. +type freezer struct { + // WARNING: The `frozen` field is accessed atomically. On 32 bit platforms, only + // 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned, + // so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG). + frozen uint64 // Number of blocks already frozen + + tables map[string]*freezerTable // Data tables for storing everything + instanceLock fileutil.Releaser // File-system lock to prevent double opens +} + +// newFreezer creates a chain freezer that moves ancient chain data into +// append-only flat file containers. +func newFreezer(datadir string, namespace string) (*freezer, error) { + // Create the initial freezer object + var ( + readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil) + writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil) + sizeGauge = metrics.NewRegisteredGauge(namespace+"ancient/size", nil) + ) + // Ensure the datadir is not a symbolic link if it exists. + if info, err := os.Lstat(datadir); !os.IsNotExist(err) { + if info.Mode()&os.ModeSymlink != 0 { + log.Warn("Symbolic link ancient database is not supported", "path", datadir) + return nil, errSymlinkDatadir + } + } + // Leveldb uses LOCK as the filelock filename. To prevent the + // name collision, we use FLOCK as the lock name. + lock, _, err := fileutil.Flock(filepath.Join(datadir, "FLOCK")) + if err != nil { + return nil, err + } + // Open all the supported data tables + freezer := &freezer{ + tables: make(map[string]*freezerTable), + instanceLock: lock, + } + for name, disableSnappy := range freezerNoSnappy { + table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy) + if err != nil { + for _, table := range freezer.tables { + table.Close() + } + lock.Release() + return nil, err + } + freezer.tables[name] = table + } + if err := freezer.repair(); err != nil { + for _, table := range freezer.tables { + table.Close() + } + lock.Release() + return nil, err + } + log.Info("Opened ancient database", "database", datadir) + return freezer, nil +} + +// Close terminates the chain freezer, unmapping all the data files. +func (f *freezer) Close() error { + var errs []error + for _, table := range f.tables { + if err := table.Close(); err != nil { + errs = append(errs, err) + } + } + if err := f.instanceLock.Release(); err != nil { + errs = append(errs, err) + } + if errs != nil { + return fmt.Errorf("%v", errs) + } + return nil +} + +// HasAncient returns an indicator whether the specified ancient data exists +// in the freezer. +func (f *freezer) HasAncient(kind string, number uint64) (bool, error) { + if table := f.tables[kind]; table != nil { + return table.has(number), nil + } + return false, nil +} + +// Ancient retrieves an ancient binary blob from the append-only immutable files. +func (f *freezer) Ancient(kind string, number uint64) ([]byte, error) { + if table := f.tables[kind]; table != nil { + return table.Retrieve(number) + } + return nil, errUnknownTable +} + +// Ancients returns the length of the frozen items. +func (f *freezer) Ancients() (uint64, error) { + return atomic.LoadUint64(&f.frozen), nil +} + +// AncientSize returns the ancient size of the specified category. +func (f *freezer) AncientSize(kind string) (uint64, error) { + if table := f.tables[kind]; table != nil { + return table.size() + } + return 0, errUnknownTable +} + +// AppendAncient injects all binary blobs belong to block at the end of the +// append-only immutable table files. +// +// Notably, this function is lock free but kind of thread-safe. All out-of-order +// injection will be rejected. But if two injections with same number happen at +// the same time, we can get into the trouble. +func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td []byte) (err error) { + // Ensure the binary blobs we are appending is continuous with freezer. + if atomic.LoadUint64(&f.frozen) != number { + return errOutOrderInsertion + } + // Rollback all inserted data if any insertion below failed to ensure + // the tables won't out of sync. + defer func() { + if err != nil { + rerr := f.repair() + if rerr != nil { + log.Crit("Failed to repair freezer", "err", rerr) + } + log.Info("Append ancient failed", "number", number, "err", err) + } + }() + // Inject all the components into the relevant data tables + if err := f.tables[freezerHashTable].Append(f.frozen, hash[:]); err != nil { + log.Error("Failed to append ancient hash", "number", f.frozen, "hash", hash, "err", err) + return err + } + if err := f.tables[freezerHeaderTable].Append(f.frozen, header); err != nil { + log.Error("Failed to append ancient header", "number", f.frozen, "hash", hash, "err", err) + return err + } + if err := f.tables[freezerBodiesTable].Append(f.frozen, body); err != nil { + log.Error("Failed to append ancient body", "number", f.frozen, "hash", hash, "err", err) + return err + } + if err := f.tables[freezerReceiptTable].Append(f.frozen, receipts); err != nil { + log.Error("Failed to append ancient receipts", "number", f.frozen, "hash", hash, "err", err) + return err + } + if err := f.tables[freezerDifficultyTable].Append(f.frozen, td); err != nil { + log.Error("Failed to append ancient difficulty", "number", f.frozen, "hash", hash, "err", err) + return err + } + atomic.AddUint64(&f.frozen, 1) // Only modify atomically + return nil +} + +// Truncate discards any recent data above the provided threshold number. +func (f *freezer) TruncateAncients(items uint64) error { + if atomic.LoadUint64(&f.frozen) <= items { + return nil + } + for _, table := range f.tables { + if err := table.truncate(items); err != nil { + return err + } + } + atomic.StoreUint64(&f.frozen, items) + return nil +} + +// sync flushes all data tables to disk. +func (f *freezer) Sync() error { + var errs []error + for _, table := range f.tables { + if err := table.Sync(); err != nil { + errs = append(errs, err) + } + } + if errs != nil { + return fmt.Errorf("%v", errs) + } + return nil +} + +// freeze is a background thread that periodically checks the blockchain for any +// import progress and moves ancient data from the fast database into the freezer. +// +// This functionality is deliberately broken off from block importing to avoid +// incurring additional data shuffling delays on block propagation. +func (f *freezer) freeze(db ethdb.KeyValueStore) { + nfdb := &nofreezedb{KeyValueStore: db} + + for { + // Retrieve the freezing threshold. + hash := ReadHeadBlockHash(nfdb) + if hash == (common.Hash{}) { + log.Debug("Current full block hash unavailable") // new chain, empty database + time.Sleep(freezerRecheckInterval) + continue + } + number := ReadHeaderNumber(nfdb, hash) + switch { + case number == nil: + log.Error("Current full block number unavailable", "hash", hash) + time.Sleep(freezerRecheckInterval) + continue + + case *number < params.ImmutabilityThreshold: + log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", params.ImmutabilityThreshold) + time.Sleep(freezerRecheckInterval) + continue + + case *number-params.ImmutabilityThreshold <= f.frozen: + log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen) + time.Sleep(freezerRecheckInterval) + continue + } + head := ReadHeader(nfdb, hash, *number) + if head == nil { + log.Error("Current full block unavailable", "number", *number, "hash", hash) + time.Sleep(freezerRecheckInterval) + continue + } + // Seems we have data ready to be frozen, process in usable batches + limit := *number - params.ImmutabilityThreshold + if limit-f.frozen > freezerBatchLimit { + limit = f.frozen + freezerBatchLimit + } + var ( + start = time.Now() + first = f.frozen + ancients = make([]common.Hash, 0, limit) + ) + for f.frozen < limit { + // Retrieves all the components of the canonical block + hash := ReadCanonicalHash(nfdb, f.frozen) + if hash == (common.Hash{}) { + log.Error("Canonical hash missing, can't freeze", "number", f.frozen) + break + } + header := ReadHeaderRLP(nfdb, hash, f.frozen) + if len(header) == 0 { + log.Error("Block header missing, can't freeze", "number", f.frozen, "hash", hash) + break + } + body := ReadBodyRLP(nfdb, hash, f.frozen) + if len(body) == 0 { + log.Error("Block body missing, can't freeze", "number", f.frozen, "hash", hash) + break + } + receipts := ReadReceiptsRLP(nfdb, hash, f.frozen) + if len(receipts) == 0 { + log.Error("Block receipts missing, can't freeze", "number", f.frozen, "hash", hash) + break + } + td := ReadTdRLP(nfdb, hash, f.frozen) + if len(td) == 0 { + log.Error("Total difficulty missing, can't freeze", "number", f.frozen, "hash", hash) + break + } + log.Trace("Deep froze ancient block", "number", f.frozen, "hash", hash) + // Inject all the components into the relevant data tables + if err := f.AppendAncient(f.frozen, hash[:], header, body, receipts, td); err != nil { + break + } + ancients = append(ancients, hash) + } + // Batch of blocks have been frozen, flush them before wiping from leveldb + if err := f.Sync(); err != nil { + log.Crit("Failed to flush frozen tables", "err", err) + } + // Wipe out all data from the active database + batch := db.NewBatch() + for i := 0; i < len(ancients); i++ { + // Always keep the genesis block in active database + if first+uint64(i) != 0 { + DeleteBlockWithoutNumber(batch, ancients[i], first+uint64(i)) + DeleteCanonicalHash(batch, first+uint64(i)) + } + } + if err := batch.Write(); err != nil { + log.Crit("Failed to delete frozen canonical blocks", "err", err) + } + batch.Reset() + // Wipe out side chain also. + for number := first; number < f.frozen; number++ { + // Always keep the genesis block in active database + if number != 0 { + for _, hash := range ReadAllHashes(db, number) { + DeleteBlock(batch, hash, number) + } + } + } + if err := batch.Write(); err != nil { + log.Crit("Failed to delete frozen side blocks", "err", err) + } + // Log something friendly for the user + context := []interface{}{ + "blocks", f.frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", f.frozen - 1, + } + if n := len(ancients); n > 0 { + context = append(context, []interface{}{"hash", ancients[n-1]}...) + } + log.Info("Deep froze chain segment", context...) + + // Avoid database thrashing with tiny writes + if f.frozen-first < freezerBatchLimit { + time.Sleep(freezerRecheckInterval) + } + } +} + +// repair truncates all data tables to the same length. +func (f *freezer) repair() error { + min := uint64(math.MaxUint64) + for _, table := range f.tables { + items := atomic.LoadUint64(&table.items) + if min > items { + min = items + } + } + for _, table := range f.tables { + if err := table.truncate(min); err != nil { + return err + } + } + atomic.StoreUint64(&f.frozen, min) + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_reinit.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_reinit.go new file mode 100644 index 000000000..ea4dd33d1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_reinit.go @@ -0,0 +1,127 @@ +// Copyright 2019 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 rawdb + +import ( + "errors" + "runtime" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/prque" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" +) + +// InitDatabaseFromFreezer reinitializes an empty database from a previous batch +// of frozen ancient blocks. The method iterates over all the frozen blocks and +// injects into the database the block hash->number mappings and the transaction +// lookup entries. +func InitDatabaseFromFreezer(db ethdb.Database) error { + // If we can't access the freezer or it's empty, abort + frozen, err := db.Ancients() + if err != nil || frozen == 0 { + return err + } + // Blocks previously frozen, iterate over- and hash them concurrently + var ( + number = ^uint64(0) // -1 + results = make(chan *types.Block, 4*runtime.NumCPU()) + ) + abort := make(chan struct{}) + defer close(abort) + + for i := 0; i < runtime.NumCPU(); i++ { + go func() { + for { + // Fetch the next task number, terminating if everything's done + n := atomic.AddUint64(&number, 1) + if n >= frozen { + return + } + // Retrieve the block from the freezer (no need for the hash, we pull by + // number from the freezer). If successful, pre-cache the block hash and + // the individual transaction hashes for storing into the database. + block := ReadBlock(db, common.Hash{}, n) + if block != nil { + block.Hash() + for _, tx := range block.Transactions() { + tx.Hash() + } + } + // Feed the block to the aggregator, or abort on interrupt + select { + case results <- block: + case <-abort: + return + } + } + }() + } + // Reassemble the blocks into a contiguous stream and push them out to disk + var ( + queue = prque.New(nil) + next = int64(0) + + batch = db.NewBatch() + start = time.Now() + logged time.Time + ) + for i := uint64(0); i < frozen; i++ { + // Retrieve the next result and bail if it's nil + block := <-results + if block == nil { + return errors.New("broken ancient database") + } + // Push the block into the import queue and process contiguous ranges + queue.Push(block, -int64(block.NumberU64())) + for !queue.Empty() { + // If the next available item is gapped, return + if _, priority := queue.Peek(); -priority != next { + break + } + // Next block available, pop it off and index it + block = queue.PopItem().(*types.Block) + next++ + + // Inject hash<->number mapping and txlookup indexes + WriteHeaderNumber(batch, block.Hash(), block.NumberU64()) + WriteTxLookupEntries(batch, block) + + // If enough data was accumulated in memory or we're at the last block, dump to disk + if batch.ValueSize() > ethdb.IdealBatchSize || uint64(next) == frozen { + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + } + // If we've spent too much time already, notify the user of what we're doing + if time.Since(logged) > 8*time.Second { + log.Info("Initializing chain from ancient data", "number", block.Number(), "hash", block.Hash(), "total", frozen-1, "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + } + hash := ReadCanonicalHash(db, frozen-1) + WriteHeadHeaderHash(db, hash) + WriteHeadFastBlockHash(db, hash) + + log.Info("Initialized chain from ancient data", "number", frozen-1, "hash", hash, "elapsed", common.PrettyDuration(time.Since(start))) + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go new file mode 100644 index 000000000..9fb341f02 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/freezer_table.go @@ -0,0 +1,637 @@ +// Copyright 2019 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 rawdb + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "sync" + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/golang/snappy" +) + +var ( + // errClosed is returned if an operation attempts to read from or write to the + // freezer table after it has already been closed. + errClosed = errors.New("closed") + + // errOutOfBounds is returned if the item requested is not contained within the + // freezer table. + errOutOfBounds = errors.New("out of bounds") + + // errNotSupported is returned if the database doesn't support the required operation. + errNotSupported = errors.New("this operation is not supported") +) + +// indexEntry contains the number/id of the file that the data resides in, aswell as the +// offset within the file to the end of the data +// In serialized form, the filenum is stored as uint16. +type indexEntry struct { + filenum uint32 // stored as uint16 ( 2 bytes) + offset uint32 // stored as uint32 ( 4 bytes) +} + +const indexEntrySize = 6 + +// unmarshallBinary deserializes binary b into the rawIndex entry. +func (i *indexEntry) unmarshalBinary(b []byte) error { + i.filenum = uint32(binary.BigEndian.Uint16(b[:2])) + i.offset = binary.BigEndian.Uint32(b[2:6]) + return nil +} + +// marshallBinary serializes the rawIndex entry into binary. +func (i *indexEntry) marshallBinary() []byte { + b := make([]byte, indexEntrySize) + binary.BigEndian.PutUint16(b[:2], uint16(i.filenum)) + binary.BigEndian.PutUint32(b[2:6], i.offset) + return b +} + +// freezerTable represents a single chained data table within the freezer (e.g. blocks). +// It consists of a data file (snappy encoded arbitrary data blobs) and an indexEntry +// file (uncompressed 64 bit indices into the data file). +type freezerTable struct { + // WARNING: The `items` field is accessed atomically. On 32 bit platforms, only + // 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned, + // so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG). + items uint64 // Number of items stored in the table (including items removed from tail) + + noCompression bool // if true, disables snappy compression. Note: does not work retroactively + maxFileSize uint32 // Max file size for data-files + name string + path string + + head *os.File // File descriptor for the data head of the table + files map[uint32]*os.File // open files + headId uint32 // number of the currently active head file + tailId uint32 // number of the earliest file + index *os.File // File descriptor for the indexEntry file of the table + + // In the case that old items are deleted (from the tail), we use itemOffset + // to count how many historic items have gone missing. + itemOffset uint32 // Offset (number of discarded items) + + headBytes uint32 // Number of bytes written to the head file + readMeter metrics.Meter // Meter for measuring the effective amount of data read + writeMeter metrics.Meter // Meter for measuring the effective amount of data written + sizeGauge metrics.Gauge // Gauge for tracking the combined size of all freezer tables + + logger log.Logger // Logger with database path and table name ambedded + lock sync.RWMutex // Mutex protecting the data file descriptors +} + +// newTable opens a freezer table with default settings - 2G files +func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeGauge metrics.Gauge, disableSnappy bool) (*freezerTable, error) { + return newCustomTable(path, name, readMeter, writeMeter, sizeGauge, 2*1000*1000*1000, disableSnappy) +} + +// openFreezerFileForAppend opens a freezer table file and seeks to the end +func openFreezerFileForAppend(filename string) (*os.File, error) { + // Open the file without the O_APPEND flag + // because it has differing behaviour during Truncate operations + // on different OS's + file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return nil, err + } + // Seek to end for append + if _, err = file.Seek(0, io.SeekEnd); err != nil { + return nil, err + } + return file, nil +} + +// openFreezerFileForReadOnly opens a freezer table file for read only access +func openFreezerFileForReadOnly(filename string) (*os.File, error) { + return os.OpenFile(filename, os.O_RDONLY, 0644) +} + +// openFreezerFileTruncated opens a freezer table making sure it is truncated +func openFreezerFileTruncated(filename string) (*os.File, error) { + return os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) +} + +// truncateFreezerFile resizes a freezer table file and seeks to the end +func truncateFreezerFile(file *os.File, size int64) error { + if err := file.Truncate(size); err != nil { + return err + } + // Seek to end for append + if _, err := file.Seek(0, io.SeekEnd); err != nil { + return err + } + return nil +} + +// newCustomTable opens a freezer table, creating the data and index files if they are +// non existent. Both files are truncated to the shortest common length to ensure +// they don't go out of sync. +func newCustomTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeGauge metrics.Gauge, maxFilesize uint32, noCompression bool) (*freezerTable, error) { + // Ensure the containing directory exists and open the indexEntry file + if err := os.MkdirAll(path, 0755); err != nil { + return nil, err + } + var idxName string + if noCompression { + // Raw idx + idxName = fmt.Sprintf("%s.ridx", name) + } else { + // Compressed idx + idxName = fmt.Sprintf("%s.cidx", name) + } + offsets, err := openFreezerFileForAppend(filepath.Join(path, idxName)) + if err != nil { + return nil, err + } + // Create the table and repair any past inconsistency + tab := &freezerTable{ + index: offsets, + files: make(map[uint32]*os.File), + readMeter: readMeter, + writeMeter: writeMeter, + sizeGauge: sizeGauge, + name: name, + path: path, + logger: log.New("database", path, "table", name), + noCompression: noCompression, + maxFileSize: maxFilesize, + } + if err := tab.repair(); err != nil { + tab.Close() + return nil, err + } + // Initialize the starting size counter + size, err := tab.sizeNolock() + if err != nil { + tab.Close() + return nil, err + } + tab.sizeGauge.Inc(int64(size)) + + return tab, nil +} + +// repair cross checks the head and the index file and truncates them to +// be in sync with each other after a potential crash / data loss. +func (t *freezerTable) repair() error { + // Create a temporary offset buffer to init files with and read indexEntry into + buffer := make([]byte, indexEntrySize) + + // If we've just created the files, initialize the index with the 0 indexEntry + stat, err := t.index.Stat() + if err != nil { + return err + } + if stat.Size() == 0 { + if _, err := t.index.Write(buffer); err != nil { + return err + } + } + // Ensure the index is a multiple of indexEntrySize bytes + if overflow := stat.Size() % indexEntrySize; overflow != 0 { + truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path + } + // Retrieve the file sizes and prepare for truncation + if stat, err = t.index.Stat(); err != nil { + return err + } + offsetsSize := stat.Size() + + // Open the head file + var ( + firstIndex indexEntry + lastIndex indexEntry + contentSize int64 + contentExp int64 + ) + // Read index zero, determine what file is the earliest + // and what item offset to use + t.index.ReadAt(buffer, 0) + firstIndex.unmarshalBinary(buffer) + + t.tailId = firstIndex.offset + t.itemOffset = firstIndex.filenum + + t.index.ReadAt(buffer, offsetsSize-indexEntrySize) + lastIndex.unmarshalBinary(buffer) + t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForAppend) + if err != nil { + return err + } + if stat, err = t.head.Stat(); err != nil { + return err + } + contentSize = stat.Size() + + // Keep truncating both files until they come in sync + contentExp = int64(lastIndex.offset) + + for contentExp != contentSize { + // Truncate the head file to the last offset pointer + if contentExp < contentSize { + t.logger.Warn("Truncating dangling head", "indexed", common.StorageSize(contentExp), "stored", common.StorageSize(contentSize)) + if err := truncateFreezerFile(t.head, contentExp); err != nil { + return err + } + contentSize = contentExp + } + // Truncate the index to point within the head file + if contentExp > contentSize { + t.logger.Warn("Truncating dangling indexes", "indexed", common.StorageSize(contentExp), "stored", common.StorageSize(contentSize)) + if err := truncateFreezerFile(t.index, offsetsSize-indexEntrySize); err != nil { + return err + } + offsetsSize -= indexEntrySize + t.index.ReadAt(buffer, offsetsSize-indexEntrySize) + var newLastIndex indexEntry + newLastIndex.unmarshalBinary(buffer) + // We might have slipped back into an earlier head-file here + if newLastIndex.filenum != lastIndex.filenum { + // Release earlier opened file + t.releaseFile(lastIndex.filenum) + if t.head, err = t.openFile(newLastIndex.filenum, openFreezerFileForAppend); err != nil { + return err + } + if stat, err = t.head.Stat(); err != nil { + // TODO, anything more we can do here? + // A data file has gone missing... + return err + } + contentSize = stat.Size() + } + lastIndex = newLastIndex + contentExp = int64(lastIndex.offset) + } + } + // Ensure all reparation changes have been written to disk + if err := t.index.Sync(); err != nil { + return err + } + if err := t.head.Sync(); err != nil { + return err + } + // Update the item and byte counters and return + t.items = uint64(t.itemOffset) + uint64(offsetsSize/indexEntrySize-1) // last indexEntry points to the end of the data file + t.headBytes = uint32(contentSize) + t.headId = lastIndex.filenum + + // Close opened files and preopen all files + if err := t.preopen(); err != nil { + return err + } + t.logger.Debug("Chain freezer table opened", "items", t.items, "size", common.StorageSize(t.headBytes)) + return nil +} + +// preopen opens all files that the freezer will need. This method should be called from an init-context, +// since it assumes that it doesn't have to bother with locking +// The rationale for doing preopen is to not have to do it from within Retrieve, thus not needing to ever +// obtain a write-lock within Retrieve. +func (t *freezerTable) preopen() (err error) { + // The repair might have already opened (some) files + t.releaseFilesAfter(0, false) + // Open all except head in RDONLY + for i := t.tailId; i < t.headId; i++ { + if _, err = t.openFile(i, openFreezerFileForReadOnly); err != nil { + return err + } + } + // Open head in read/write + t.head, err = t.openFile(t.headId, openFreezerFileForAppend) + return err +} + +// truncate discards any recent data above the provided threshold number. +func (t *freezerTable) truncate(items uint64) error { + t.lock.Lock() + defer t.lock.Unlock() + + // If our item count is correct, don't do anything + if atomic.LoadUint64(&t.items) <= items { + return nil + } + // We need to truncate, save the old size for metrics tracking + oldSize, err := t.sizeNolock() + if err != nil { + return err + } + // Something's out of sync, truncate the table's offset index + t.logger.Warn("Truncating freezer table", "items", t.items, "limit", items) + if err := truncateFreezerFile(t.index, int64(items+1)*indexEntrySize); err != nil { + return err + } + // Calculate the new expected size of the data file and truncate it + buffer := make([]byte, indexEntrySize) + if _, err := t.index.ReadAt(buffer, int64(items*indexEntrySize)); err != nil { + return err + } + var expected indexEntry + expected.unmarshalBinary(buffer) + + // We might need to truncate back to older files + if expected.filenum != t.headId { + // If already open for reading, force-reopen for writing + t.releaseFile(expected.filenum) + newHead, err := t.openFile(expected.filenum, openFreezerFileForAppend) + if err != nil { + return err + } + // Release any files _after the current head -- both the previous head + // and any files which may have been opened for reading + t.releaseFilesAfter(expected.filenum, true) + // Set back the historic head + t.head = newHead + atomic.StoreUint32(&t.headId, expected.filenum) + } + if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil { + return err + } + // All data files truncated, set internal counters and return + atomic.StoreUint64(&t.items, items) + atomic.StoreUint32(&t.headBytes, expected.offset) + + // Retrieve the new size and update the total size counter + newSize, err := t.sizeNolock() + if err != nil { + return err + } + t.sizeGauge.Dec(int64(oldSize - newSize)) + + return nil +} + +// Close closes all opened files. +func (t *freezerTable) Close() error { + t.lock.Lock() + defer t.lock.Unlock() + + var errs []error + if err := t.index.Close(); err != nil { + errs = append(errs, err) + } + t.index = nil + + for _, f := range t.files { + if err := f.Close(); err != nil { + errs = append(errs, err) + } + } + t.head = nil + + if errs != nil { + return fmt.Errorf("%v", errs) + } + return nil +} + +// openFile assumes that the write-lock is held by the caller +func (t *freezerTable) openFile(num uint32, opener func(string) (*os.File, error)) (f *os.File, err error) { + var exist bool + if f, exist = t.files[num]; !exist { + var name string + if t.noCompression { + name = fmt.Sprintf("%s.%04d.rdat", t.name, num) + } else { + name = fmt.Sprintf("%s.%04d.cdat", t.name, num) + } + f, err = opener(filepath.Join(t.path, name)) + if err != nil { + return nil, err + } + t.files[num] = f + } + return f, err +} + +// releaseFile closes a file, and removes it from the open file cache. +// Assumes that the caller holds the write lock +func (t *freezerTable) releaseFile(num uint32) { + if f, exist := t.files[num]; exist { + delete(t.files, num) + f.Close() + } +} + +// releaseFilesAfter closes all open files with a higher number, and optionally also deletes the files +func (t *freezerTable) releaseFilesAfter(num uint32, remove bool) { + for fnum, f := range t.files { + if fnum > num { + delete(t.files, fnum) + f.Close() + if remove { + os.Remove(f.Name()) + } + } + } +} + +// Append injects a binary blob at the end of the freezer table. The item number +// is a precautionary parameter to ensure data correctness, but the table will +// reject already existing data. +// +// Note, this method will *not* flush any data to disk so be sure to explicitly +// fsync before irreversibly deleting data from the database. +func (t *freezerTable) Append(item uint64, blob []byte) error { + // Read lock prevents competition with truncate + t.lock.RLock() + // Ensure the table is still accessible + if t.index == nil || t.head == nil { + t.lock.RUnlock() + return errClosed + } + // Ensure only the next item can be written, nothing else + if atomic.LoadUint64(&t.items) != item { + t.lock.RUnlock() + return fmt.Errorf("appending unexpected item: want %d, have %d", t.items, item) + } + // Encode the blob and write it into the data file + if !t.noCompression { + blob = snappy.Encode(nil, blob) + } + bLen := uint32(len(blob)) + if t.headBytes+bLen < bLen || + t.headBytes+bLen > t.maxFileSize { + // we need a new file, writing would overflow + t.lock.RUnlock() + t.lock.Lock() + nextID := atomic.LoadUint32(&t.headId) + 1 + // We open the next file in truncated mode -- if this file already + // exists, we need to start over from scratch on it + newHead, err := t.openFile(nextID, openFreezerFileTruncated) + if err != nil { + t.lock.Unlock() + return err + } + // Close old file, and reopen in RDONLY mode + t.releaseFile(t.headId) + t.openFile(t.headId, openFreezerFileForReadOnly) + + // Swap out the current head + t.head = newHead + atomic.StoreUint32(&t.headBytes, 0) + atomic.StoreUint32(&t.headId, nextID) + t.lock.Unlock() + t.lock.RLock() + } + + defer t.lock.RUnlock() + if _, err := t.head.Write(blob); err != nil { + return err + } + newOffset := atomic.AddUint32(&t.headBytes, bLen) + idx := indexEntry{ + filenum: atomic.LoadUint32(&t.headId), + offset: newOffset, + } + // Write indexEntry + t.index.Write(idx.marshallBinary()) + + t.writeMeter.Mark(int64(bLen + indexEntrySize)) + t.sizeGauge.Inc(int64(bLen + indexEntrySize)) + + atomic.AddUint64(&t.items, 1) + return nil +} + +// getBounds returns the indexes for the item +// returns start, end, filenumber and error +func (t *freezerTable) getBounds(item uint64) (uint32, uint32, uint32, error) { + var startIdx, endIdx indexEntry + buffer := make([]byte, indexEntrySize) + if _, err := t.index.ReadAt(buffer, int64(item*indexEntrySize)); err != nil { + return 0, 0, 0, err + } + startIdx.unmarshalBinary(buffer) + if _, err := t.index.ReadAt(buffer, int64((item+1)*indexEntrySize)); err != nil { + return 0, 0, 0, err + } + endIdx.unmarshalBinary(buffer) + if startIdx.filenum != endIdx.filenum { + // If a piece of data 'crosses' a data-file, + // it's actually in one piece on the second data-file. + // We return a zero-indexEntry for the second file as start + return 0, endIdx.offset, endIdx.filenum, nil + } + return startIdx.offset, endIdx.offset, endIdx.filenum, nil +} + +// Retrieve looks up the data offset of an item with the given number and retrieves +// the raw binary blob from the data file. +func (t *freezerTable) Retrieve(item uint64) ([]byte, error) { + // Ensure the table and the item is accessible + if t.index == nil || t.head == nil { + return nil, errClosed + } + if atomic.LoadUint64(&t.items) <= item { + return nil, errOutOfBounds + } + // Ensure the item was not deleted from the tail either + offset := atomic.LoadUint32(&t.itemOffset) + if uint64(offset) > item { + return nil, errOutOfBounds + } + t.lock.RLock() + startOffset, endOffset, filenum, err := t.getBounds(item - uint64(offset)) + if err != nil { + t.lock.RUnlock() + return nil, err + } + dataFile, exist := t.files[filenum] + if !exist { + t.lock.RUnlock() + return nil, fmt.Errorf("missing data file %d", filenum) + } + // Retrieve the data itself, decompress and return + blob := make([]byte, endOffset-startOffset) + if _, err := dataFile.ReadAt(blob, int64(startOffset)); err != nil { + t.lock.RUnlock() + return nil, err + } + t.lock.RUnlock() + t.readMeter.Mark(int64(len(blob) + 2*indexEntrySize)) + + if t.noCompression { + return blob, nil + } + return snappy.Decode(nil, blob) +} + +// has returns an indicator whether the specified number data +// exists in the freezer table. +func (t *freezerTable) has(number uint64) bool { + return atomic.LoadUint64(&t.items) > number +} + +// size returns the total data size in the freezer table. +func (t *freezerTable) size() (uint64, error) { + t.lock.RLock() + defer t.lock.RUnlock() + + return t.sizeNolock() +} + +// sizeNolock returns the total data size in the freezer table without obtaining +// the mutex first. +func (t *freezerTable) sizeNolock() (uint64, error) { + stat, err := t.index.Stat() + if err != nil { + return 0, err + } + total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size()) + return total, nil +} + +// Sync pushes any pending data from memory out to disk. This is an expensive +// operation, so use it with care. +func (t *freezerTable) Sync() error { + if err := t.index.Sync(); err != nil { + return err + } + return t.head.Sync() +} + +// printIndex is a debug print utility function for testing +func (t *freezerTable) printIndex() { + buf := make([]byte, indexEntrySize) + + fmt.Printf("|-----------------|\n") + fmt.Printf("| fileno | offset |\n") + fmt.Printf("|--------+--------|\n") + + for i := uint64(0); ; i++ { + if _, err := t.index.ReadAt(buf, int64(i*indexEntrySize)); err != nil { + break + } + var entry indexEntry + entry.unmarshalBinary(buf) + fmt.Printf("| %03d | %03d | \n", entry.filenum, entry.offset) + if i > 100 { + fmt.Printf(" ... \n") + break + } + } + fmt.Printf("|-----------------|\n") +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go index 8a9921ef4..a44a2c99f 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/schema.go @@ -29,10 +29,10 @@ var ( // databaseVerisionKey tracks the current database version. databaseVerisionKey = []byte("DatabaseVersion") - // headHeaderKey tracks the latest know header's hash. + // headHeaderKey tracks the latest known header's hash. headHeaderKey = []byte("LastHeader") - // headBlockKey tracks the latest know full block's hash. + // headBlockKey tracks the latest known full block's hash. headBlockKey = []byte("LastBlock") // headFastBlockKey tracks the latest known incomplete block's hash during fast sync. @@ -63,9 +63,36 @@ var ( preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) ) -// TxLookupEntry is a positional metadata to help looking up the data content of -// a transaction or receipt given only its hash. -type TxLookupEntry struct { +const ( + // freezerHeaderTable indicates the name of the freezer header table. + freezerHeaderTable = "headers" + + // freezerHashTable indicates the name of the freezer canonical hash table. + freezerHashTable = "hashes" + + // freezerBodiesTable indicates the name of the freezer block body table. + freezerBodiesTable = "bodies" + + // freezerReceiptTable indicates the name of the freezer receipts table. + freezerReceiptTable = "receipts" + + // freezerDifficultyTable indicates the name of the freezer total difficulty table. + freezerDifficultyTable = "diffs" +) + +// freezerNoSnappy configures whether compression is disabled for the ancient-tables. +// Hashes and difficulties don't compress well. +var freezerNoSnappy = map[string]bool{ + freezerHeaderTable: false, + freezerHashTable: true, + freezerBodiesTable: false, + freezerReceiptTable: false, + freezerDifficultyTable: true, +} + +// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary +// fields. +type LegacyTxLookupEntry struct { BlockHash common.Hash BlockIndex uint64 Index uint64 @@ -78,6 +105,11 @@ func encodeBlockNumber(number uint64) []byte { return enc } +// headerKeyPrefix = headerPrefix + num (uint64 big endian) +func headerKeyPrefix(number uint64) []byte { + return append(headerPrefix, encodeBlockNumber(number)...) +} + // headerKey = headerPrefix + num (uint64 big endian) + hash func headerKey(number uint64, hash common.Hash) []byte { return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go b/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go new file mode 100644 index 000000000..6610b7f5a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/rawdb/table.go @@ -0,0 +1,204 @@ +// 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 rawdb + +import ( + "github.com/ethereum/go-ethereum/ethdb" +) + +// table is a wrapper around a database that prefixes each key access with a pre- +// configured string. +type table struct { + db ethdb.Database + prefix string +} + +// NewTable returns a database object that prefixes all keys with a given string. +func NewTable(db ethdb.Database, prefix string) ethdb.Database { + return &table{ + db: db, + prefix: prefix, + } +} + +// Close is a noop to implement the Database interface. +func (t *table) Close() error { + return nil +} + +// Has retrieves if a prefixed version of a key is present in the database. +func (t *table) Has(key []byte) (bool, error) { + return t.db.Has(append([]byte(t.prefix), key...)) +} + +// Get retrieves the given prefixed key if it's present in the database. +func (t *table) Get(key []byte) ([]byte, error) { + return t.db.Get(append([]byte(t.prefix), key...)) +} + +// HasAncient is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) HasAncient(kind string, number uint64) (bool, error) { + return t.db.HasAncient(kind, number) +} + +// Ancient is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) Ancient(kind string, number uint64) ([]byte, error) { + return t.db.Ancient(kind, number) +} + +// Ancients is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) Ancients() (uint64, error) { + return t.db.Ancients() +} + +// AncientSize is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) AncientSize(kind string) (uint64, error) { + return t.db.AncientSize(kind) +} + +// AppendAncient is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error { + return t.db.AppendAncient(number, hash, header, body, receipts, td) +} + +// TruncateAncients is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) TruncateAncients(items uint64) error { + return t.db.TruncateAncients(items) +} + +// Sync is a noop passthrough that just forwards the request to the underlying +// database. +func (t *table) Sync() error { + return t.db.Sync() +} + +// Put inserts the given value into the database at a prefixed version of the +// provided key. +func (t *table) Put(key []byte, value []byte) error { + return t.db.Put(append([]byte(t.prefix), key...), value) +} + +// Delete removes the given prefixed key from the database. +func (t *table) Delete(key []byte) error { + return t.db.Delete(append([]byte(t.prefix), key...)) +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the database. +func (t *table) NewIterator() ethdb.Iterator { + return t.NewIteratorWithPrefix(nil) +} + +// NewIteratorWithStart creates a binary-alphabetical iterator over a subset of +// database content starting at a particular initial key (or after, if it does +// not exist). +func (t *table) NewIteratorWithStart(start []byte) ethdb.Iterator { + return t.db.NewIteratorWithStart(start) +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (t *table) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + return t.db.NewIteratorWithPrefix(append([]byte(t.prefix), prefix...)) +} + +// Stat returns a particular internal stat of the database. +func (t *table) Stat(property string) (string, error) { + return t.db.Stat(property) +} + +// Compact flattens the underlying data store for the given key range. In essence, +// deleted and overwritten versions are discarded, and the data is rearranged to +// reduce the cost of operations needed to access them. +// +// A nil start is treated as a key before all keys in the data store; a nil limit +// is treated as a key after all keys in the data store. If both is nil then it +// will compact entire data store. +func (t *table) Compact(start []byte, limit []byte) error { + // If no start was specified, use the table prefix as the first value + if start == nil { + start = []byte(t.prefix) + } + // If no limit was specified, use the first element not matching the prefix + // as the limit + if limit == nil { + limit = []byte(t.prefix) + for i := len(limit) - 1; i >= 0; i-- { + // Bump the current character, stopping if it doesn't overflow + limit[i]++ + if limit[i] > 0 { + break + } + // Character overflown, proceed to the next or nil if the last + if i == 0 { + limit = nil + } + } + } + // Range correctly calculated based on table prefix, delegate down + return t.db.Compact(start, limit) +} + +// NewBatch creates a write-only database that buffers changes to its host db +// until a final write is called, each operation prefixing all keys with the +// pre-configured string. +func (t *table) NewBatch() ethdb.Batch { + return &tableBatch{t.db.NewBatch(), t.prefix} +} + +// tableBatch is a wrapper around a database batch that prefixes each key access +// with a pre-configured string. +type tableBatch struct { + batch ethdb.Batch + prefix string +} + +// Put inserts the given value into the batch for later committing. +func (b *tableBatch) Put(key, value []byte) error { + return b.batch.Put(append([]byte(b.prefix), key...), value) +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *tableBatch) Delete(key []byte) error { + return b.batch.Delete(append([]byte(b.prefix), key...)) +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *tableBatch) ValueSize() int { + return b.batch.ValueSize() +} + +// Write flushes any accumulated data to disk. +func (b *tableBatch) Write() error { + return b.batch.Write() +} + +// Reset resets the batch for reuse. +func (b *tableBatch) Reset() { + b.batch.Reset() +} + +// Replay replays the batch contents. +func (b *tableBatch) Replay(w ethdb.KeyValueWriter) error { + return b.batch.Replay(w) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/database.go b/vendor/github.com/ethereum/go-ethereum/core/state/database.go index f6ea144b9..ecc2c134d 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/database.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/database.go @@ -18,7 +18,6 @@ package state import ( "fmt" - "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" @@ -26,14 +25,7 @@ import ( lru "github.com/hashicorp/golang-lru" ) -// Trie cache generation limit after which to evict trie nodes from memory. -var MaxTrieCacheGen = uint16(120) - const ( - // Number of past tries to keep. This value is chosen such that - // reasonable chain reorg depths will hit an existing trie. - maxPastTries = 12 - // Number of codehash->size associations to keep. codeSizeCacheSize = 100000 ) @@ -59,28 +51,61 @@ type Database interface { TrieDB() *trie.Database } -// Trie is a Ethereum Merkle Trie. +// Trie is a Ethereum Merkle Patricia trie. type Trie interface { + // GetKey returns the sha3 preimage of a hashed key that was previously used + // to store a value. + // + // TODO(fjl): remove this when SecureTrie is removed + GetKey([]byte) []byte + + // TryGet returns the value for key stored in the trie. The value bytes must + // not be modified by the caller. If a node was not found in the database, a + // trie.MissingNodeError is returned. TryGet(key []byte) ([]byte, error) + + // TryUpdate associates key with value in the trie. If value has length zero, any + // existing value is deleted from the trie. The value bytes must not be modified + // by the caller while they are stored in the trie. If a node was not found in the + // database, a trie.MissingNodeError is returned. TryUpdate(key, value []byte) error + + // TryDelete removes any existing value for key from the trie. If a node was not + // found in the database, a trie.MissingNodeError is returned. TryDelete(key []byte) error - Commit(onleaf trie.LeafCallback) (common.Hash, error) + + // Hash returns the root hash of the trie. It does not write to the database and + // can be used even if the trie doesn't have one. Hash() common.Hash + + // Commit writes all nodes to the trie's memory database, tracking the internal + // and external (for account tries) references. + Commit(onleaf trie.LeafCallback) (common.Hash, error) + + // NodeIterator returns an iterator that returns nodes of the trie. Iteration + // starts at the key after the given start key. NodeIterator(startKey []byte) trie.NodeIterator - GetKey([]byte) []byte // TODO(fjl): remove this when SecureTrie is removed - Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error + + // Prove constructs a Merkle proof for key. The result contains all encoded nodes + // on the path to the value at key. The value itself is also included in the last + // node and can be retrieved by verifying the proof. + // + // If the trie does not contain a value for key, the returned proof contains all + // nodes of the longest existing prefix of the key (at least the root), ending + // with the node that proves the absence of the key. + Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error } // NewDatabase creates a backing store for state. The returned database is safe for -// concurrent use and retains a few recent expanded trie nodes in memory. To keep -// more historical state in memory, use the NewDatabaseWithCache constructor. +// concurrent use, but does not retain any recent trie nodes in memory. To keep some +// historical state in memory, use the NewDatabaseWithCache constructor. func NewDatabase(db ethdb.Database) Database { return NewDatabaseWithCache(db, 0) } -// NewDatabase creates a backing store for state. The returned database is safe for -// concurrent use and retains both a few recent expanded trie nodes in memory, as -// well as a lot of collapsed RLP trie nodes in a large memory cache. +// NewDatabaseWithCache creates a backing store for state. The returned database +// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a +// large memory cache. func NewDatabaseWithCache(db ethdb.Database, cache int) Database { csc, _ := lru.New(codeSizeCacheSize) return &cachingDB{ @@ -91,50 +116,22 @@ func NewDatabaseWithCache(db ethdb.Database, cache int) Database { type cachingDB struct { db *trie.Database - mu sync.Mutex - pastTries []*trie.SecureTrie codeSizeCache *lru.Cache } -// OpenTrie opens the main account trie. +// OpenTrie opens the main account trie at a specific root hash. func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { - db.mu.Lock() - defer db.mu.Unlock() - - for i := len(db.pastTries) - 1; i >= 0; i-- { - if db.pastTries[i].Hash() == root { - return cachedTrie{db.pastTries[i].Copy(), db}, nil - } - } - tr, err := trie.NewSecure(root, db.db, MaxTrieCacheGen) - if err != nil { - return nil, err - } - return cachedTrie{tr, db}, nil -} - -func (db *cachingDB) pushTrie(t *trie.SecureTrie) { - db.mu.Lock() - defer db.mu.Unlock() - - if len(db.pastTries) >= maxPastTries { - copy(db.pastTries, db.pastTries[1:]) - db.pastTries[len(db.pastTries)-1] = t - } else { - db.pastTries = append(db.pastTries, t) - } + return trie.NewSecure(root, db.db) } // OpenStorageTrie opens the storage trie of an account. func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { - return trie.NewSecure(root, db.db, 0) + return trie.NewSecure(root, db.db) } // CopyTrie returns an independent copy of the given trie. func (db *cachingDB) CopyTrie(t Trie) Trie { switch t := t.(type) { - case cachedTrie: - return cachedTrie{t.SecureTrie.Copy(), db} case *trie.SecureTrie: return t.Copy() default: @@ -164,21 +161,3 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro func (db *cachingDB) TrieDB() *trie.Database { return db.db } - -// cachedTrie inserts its trie into a cachingDB on commit. -type cachedTrie struct { - *trie.SecureTrie - db *cachingDB -} - -func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) { - root, err := m.SecureTrie.Commit(onleaf) - if err == nil { - m.db.pushTrie(m.SecureTrie) - } - return root, err -} - -func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { - return m.SecureTrie.Prove(key, fromLevel, proofDb) -} diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/dump.go b/vendor/github.com/ethereum/go-ethereum/core/state/dump.go index 072dbbf05..7912fd5f9 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/dump.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/dump.go @@ -21,61 +21,138 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) +// DumpAccount represents an account in the state type DumpAccount struct { - Balance string `json:"balance"` - Nonce uint64 `json:"nonce"` - Root string `json:"root"` - CodeHash string `json:"codeHash"` - Code string `json:"code"` - Storage map[string]string `json:"storage"` + Balance string `json:"balance"` + Nonce uint64 `json:"nonce"` + Root string `json:"root"` + CodeHash string `json:"codeHash"` + Code string `json:"code,omitempty"` + Storage map[common.Hash]string `json:"storage,omitempty"` + Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode + SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key + } +// Dump represents the full dump in a collected format, as one large map type Dump struct { - Root string `json:"root"` - Accounts map[string]DumpAccount `json:"accounts"` + Root string `json:"root"` + Accounts map[common.Address]DumpAccount `json:"accounts"` } -func (self *StateDB) RawDump() Dump { - dump := Dump{ - Root: fmt.Sprintf("%x", self.trie.Hash()), - Accounts: make(map[string]DumpAccount), - } +// iterativeDump is a 'collector'-implementation which dump output line-by-line iteratively +type iterativeDump json.Encoder +// Collector interface which the state trie calls during iteration +type collector interface { + onRoot(common.Hash) + onAccount(common.Address, DumpAccount) +} + +func (self *Dump) onRoot(root common.Hash) { + self.Root = fmt.Sprintf("%x", root) +} + +func (self *Dump) onAccount(addr common.Address, account DumpAccount) { + self.Accounts[addr] = account +} + +func (self iterativeDump) onAccount(addr common.Address, account DumpAccount) { + dumpAccount := &DumpAccount{ + Balance: account.Balance, + Nonce: account.Nonce, + Root: account.Root, + CodeHash: account.CodeHash, + Code: account.Code, + Storage: account.Storage, + SecureKey: account.SecureKey, + Address: nil, + } + if addr != (common.Address{}) { + dumpAccount.Address = &addr + } + (*json.Encoder)(&self).Encode(dumpAccount) +} +func (self iterativeDump) onRoot(root common.Hash) { + (*json.Encoder)(&self).Encode(struct { + Root common.Hash `json:"root"` + }{root}) +} + +func (self *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissingPreimages bool) { + emptyAddress := (common.Address{}) + missingPreimages := 0 + c.onRoot(self.trie.Hash()) it := trie.NewIterator(self.trie.NodeIterator(nil)) for it.Next() { - addr := self.trie.GetKey(it.Key) var data Account if err := rlp.DecodeBytes(it.Value, &data); err != nil { panic(err) } - - obj := newObject(nil, common.BytesToAddress(addr), data) + addr := common.BytesToAddress(self.trie.GetKey(it.Key)) + obj := newObject(nil, addr, data) account := DumpAccount{ Balance: data.Balance.String(), Nonce: data.Nonce, Root: common.Bytes2Hex(data.Root[:]), CodeHash: common.Bytes2Hex(data.CodeHash), - Code: common.Bytes2Hex(obj.Code(self.db)), - Storage: make(map[string]string), } - storageIt := trie.NewIterator(obj.getTrie(self.db).NodeIterator(nil)) - for storageIt.Next() { - account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) + if emptyAddress == addr { + // Preimage missing + missingPreimages++ + if excludeMissingPreimages { + continue + } + account.SecureKey = it.Key } - dump.Accounts[common.Bytes2Hex(addr)] = account + if !excludeCode { + account.Code = common.Bytes2Hex(obj.Code(self.db)) + } + if !excludeStorage { + account.Storage = make(map[common.Hash]string) + storageIt := trie.NewIterator(obj.getTrie(self.db).NodeIterator(nil)) + for storageIt.Next() { + _, content, _, err := rlp.Split(storageIt.Value) + if err != nil { + log.Error("Failed to decode the value returned by iterator", "error", err) + continue + } + account.Storage[common.BytesToHash(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(content) + } + } + c.onAccount(addr, account) + } + if missingPreimages > 0 { + log.Warn("Dump incomplete due to missing preimages", "missing", missingPreimages) } - return dump } -func (self *StateDB) Dump() []byte { - json, err := json.MarshalIndent(self.RawDump(), "", " ") +// RawDump returns the entire state an a single large object +func (self *StateDB) RawDump(excludeCode, excludeStorage, excludeMissingPreimages bool) Dump { + dump := &Dump{ + Accounts: make(map[common.Address]DumpAccount), + } + self.dump(dump, excludeCode, excludeStorage, excludeMissingPreimages) + return *dump +} + +// Dump returns a JSON string representing the entire state as a single json-object +func (self *StateDB) Dump(excludeCode, excludeStorage, excludeMissingPreimages bool) []byte { + dump := self.RawDump(excludeCode, excludeStorage, excludeMissingPreimages) + json, err := json.MarshalIndent(dump, "", " ") if err != nil { fmt.Println("dump err", err) } - return json } + +// IterativeDump dumps out accounts as json-objects, delimited by linebreaks on stdout +func (self *StateDB) IterativeDump(excludeCode, excludeStorage, excludeMissingPreimages bool, output *json.Encoder) { + self.dump(iterativeDump(*output), excludeCode, excludeStorage, excludeMissingPreimages) +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/managed_state.go b/vendor/github.com/ethereum/go-ethereum/core/state/managed_state.go deleted file mode 100644 index 1390ef4a0..000000000 --- a/vendor/github.com/ethereum/go-ethereum/core/state/managed_state.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package state - -import ( - "sync" - - "github.com/ethereum/go-ethereum/common" -) - -type account struct { - stateObject *stateObject - nstart uint64 - nonces []bool -} - -type ManagedState struct { - *StateDB - - mu sync.RWMutex - - accounts map[common.Address]*account -} - -// ManagedState returns a new managed state with the statedb as it's backing layer -func ManageState(statedb *StateDB) *ManagedState { - return &ManagedState{ - StateDB: statedb.Copy(), - accounts: make(map[common.Address]*account), - } -} - -// SetState sets the backing layer of the managed state -func (ms *ManagedState) SetState(statedb *StateDB) { - ms.mu.Lock() - defer ms.mu.Unlock() - ms.StateDB = statedb -} - -// RemoveNonce removed the nonce from the managed state and all future pending nonces -func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { - if ms.hasAccount(addr) { - ms.mu.Lock() - defer ms.mu.Unlock() - - account := ms.getAccount(addr) - if n-account.nstart <= uint64(len(account.nonces)) { - reslice := make([]bool, n-account.nstart) - copy(reslice, account.nonces[:n-account.nstart]) - account.nonces = reslice - } - } -} - -// NewNonce returns the new canonical nonce for the managed account -func (ms *ManagedState) NewNonce(addr common.Address) uint64 { - ms.mu.Lock() - defer ms.mu.Unlock() - - account := ms.getAccount(addr) - for i, nonce := range account.nonces { - if !nonce { - return account.nstart + uint64(i) - } - } - account.nonces = append(account.nonces, true) - - return uint64(len(account.nonces)-1) + account.nstart -} - -// GetNonce returns the canonical nonce for the managed or unmanaged account. -// -// Because GetNonce mutates the DB, we must take a write lock. -func (ms *ManagedState) GetNonce(addr common.Address) uint64 { - ms.mu.Lock() - defer ms.mu.Unlock() - - if ms.hasAccount(addr) { - account := ms.getAccount(addr) - return uint64(len(account.nonces)) + account.nstart - } else { - return ms.StateDB.GetNonce(addr) - } -} - -// SetNonce sets the new canonical nonce for the managed state -func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { - ms.mu.Lock() - defer ms.mu.Unlock() - - so := ms.GetOrNewStateObject(addr) - so.SetNonce(nonce) - - ms.accounts[addr] = newAccount(so) -} - -// HasAccount returns whether the given address is managed or not -func (ms *ManagedState) HasAccount(addr common.Address) bool { - ms.mu.RLock() - defer ms.mu.RUnlock() - return ms.hasAccount(addr) -} - -func (ms *ManagedState) hasAccount(addr common.Address) bool { - _, ok := ms.accounts[addr] - return ok -} - -// populate the managed state -func (ms *ManagedState) getAccount(addr common.Address) *account { - if account, ok := ms.accounts[addr]; !ok { - so := ms.GetOrNewStateObject(addr) - ms.accounts[addr] = newAccount(so) - } else { - // Always make sure the state account nonce isn't actually higher - // than the tracked one. - so := ms.StateDB.getStateObject(addr) - if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() { - ms.accounts[addr] = newAccount(so) - } - - } - - return ms.accounts[addr] -} - -func newAccount(so *stateObject) *account { - return &account{so, so.Nonce(), nil} -} diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go index f41ab0409..8680de021 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/state_object.go @@ -21,9 +21,11 @@ import ( "fmt" "io" "math/big" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" ) @@ -31,23 +33,23 @@ var emptyCodeHash = crypto.Keccak256(nil) type Code []byte -func (self Code) String() string { - return string(self) //strings.Join(Disassemble(self), " ") +func (c Code) String() string { + return string(c) //strings.Join(Disassemble(c), " ") } type Storage map[common.Hash]common.Hash -func (self Storage) String() (str string) { - for key, value := range self { +func (s Storage) String() (str string) { + for key, value := range s { str += fmt.Sprintf("%X : %X\n", key, value) } return } -func (self Storage) Copy() Storage { +func (s Storage) Copy() Storage { cpy := make(Storage) - for key, value := range self { + for key, value := range s { cpy[key] = value } @@ -77,8 +79,10 @@ type stateObject struct { trie Trie // storage trie, which becomes non-nil on first access code Code // contract bytecode, which gets set when code is loaded - originStorage Storage // Storage cache of original entries to dedup rewrites - dirtyStorage Storage // Storage entries that need to be flushed to disk + originStorage Storage // Storage cache of original entries to dedup rewrites, reset for every transaction + pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block + dirtyStorage Storage // Storage entries that have been modified in the current transaction execution + fakeStorage Storage // Fake storage which constructed by caller for debugging purpose. // Cache flags. // When an object is marked suicided it will be delete from the trie @@ -110,203 +114,275 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject { if data.CodeHash == nil { data.CodeHash = emptyCodeHash } + if data.Root == (common.Hash{}) { + data.Root = emptyRoot + } return &stateObject{ - db: db, - address: address, - addrHash: crypto.Keccak256Hash(address[:]), - data: data, - originStorage: make(Storage), - dirtyStorage: make(Storage), + db: db, + address: address, + addrHash: crypto.Keccak256Hash(address[:]), + data: data, + originStorage: make(Storage), + pendingStorage: make(Storage), + dirtyStorage: make(Storage), } } // EncodeRLP implements rlp.Encoder. -func (c *stateObject) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, c.data) +func (s *stateObject) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, s.data) } // setError remembers the first non-nil error it is called with. -func (self *stateObject) setError(err error) { - if self.dbErr == nil { - self.dbErr = err +func (s *stateObject) setError(err error) { + if s.dbErr == nil { + s.dbErr = err } } -func (self *stateObject) markSuicided() { - self.suicided = true +func (s *stateObject) markSuicided() { + s.suicided = true } -func (c *stateObject) touch() { - c.db.journal.append(touchChange{ - account: &c.address, +func (s *stateObject) touch() { + s.db.journal.append(touchChange{ + account: &s.address, }) - if c.address == ripemd { + if s.address == ripemd { // Explicitly put it in the dirty-cache, which is otherwise generated from // flattened journals. - c.db.journal.dirty(c.address) + s.db.journal.dirty(s.address) } } -func (c *stateObject) getTrie(db Database) Trie { - if c.trie == nil { +func (s *stateObject) getTrie(db Database) Trie { + if s.trie == nil { var err error - c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root) + s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) if err != nil { - c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{}) - c.setError(fmt.Errorf("can't create storage trie: %v", err)) + s.trie, _ = db.OpenStorageTrie(s.addrHash, common.Hash{}) + s.setError(fmt.Errorf("can't create storage trie: %v", err)) } } - return c.trie + return s.trie } // GetState retrieves a value from the account storage trie. -func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { +func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { + // If the fake storage is set, only lookup the state here(in the debugging mode) + if s.fakeStorage != nil { + return s.fakeStorage[key] + } // If we have a dirty value for this state entry, return it - value, dirty := self.dirtyStorage[key] + value, dirty := s.dirtyStorage[key] if dirty { return value } // Otherwise return the entry's original value - return self.GetCommittedState(db, key) + return s.GetCommittedState(db, key) } // GetCommittedState retrieves a value from the committed account storage trie. -func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { - // If we have the original value cached, return that - value, cached := self.originStorage[key] - if cached { +func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { + // If the fake storage is set, only lookup the state here(in the debugging mode) + if s.fakeStorage != nil { + return s.fakeStorage[key] + } + // If we have a pending write or clean cached, return that + if value, pending := s.pendingStorage[key]; pending { return value } + if value, cached := s.originStorage[key]; cached { + return value + } + // Track the amount of time wasted on reading the storage trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.db.StorageReads += time.Since(start) }(time.Now()) + } // Otherwise load the value from the database - enc, err := self.getTrie(db).TryGet(key[:]) + enc, err := s.getTrie(db).TryGet(key[:]) if err != nil { - self.setError(err) + s.setError(err) return common.Hash{} } + var value common.Hash if len(enc) > 0 { _, content, _, err := rlp.Split(enc) if err != nil { - self.setError(err) + s.setError(err) } value.SetBytes(content) } - self.originStorage[key] = value + s.originStorage[key] = value return value } // SetState updates a value in account storage. -func (self *stateObject) SetState(db Database, key, value common.Hash) { +func (s *stateObject) SetState(db Database, key, value common.Hash) { + // If the fake storage is set, put the temporary state update here. + if s.fakeStorage != nil { + s.fakeStorage[key] = value + return + } // If the new value is the same as old, don't set - prev := self.GetState(db, key) + prev := s.GetState(db, key) if prev == value { return } // New value is different, update and journal the change - self.db.journal.append(storageChange{ - account: &self.address, + s.db.journal.append(storageChange{ + account: &s.address, key: key, prevalue: prev, }) - self.setState(key, value) + s.setState(key, value) } -func (self *stateObject) setState(key, value common.Hash) { - self.dirtyStorage[key] = value +// SetStorage replaces the entire state storage with the given one. +// +// After this function is called, all original state will be ignored and state +// lookup only happens in the fake state storage. +// +// Note this function should only be used for debugging purpose. +func (s *stateObject) SetStorage(storage map[common.Hash]common.Hash) { + // Allocate fake storage if it's nil. + if s.fakeStorage == nil { + s.fakeStorage = make(Storage) + } + for key, value := range storage { + s.fakeStorage[key] = value + } + // Don't bother journal since this function should only be used for + // debugging and the `fake` storage won't be committed to database. +} + +func (s *stateObject) setState(key, value common.Hash) { + s.dirtyStorage[key] = value +} + +// finalise moves all dirty storage slots into the pending area to be hashed or +// committed later. It is invoked at the end of every transaction. +func (s *stateObject) finalise() { + for key, value := range s.dirtyStorage { + s.pendingStorage[key] = value + } + if len(s.dirtyStorage) > 0 { + s.dirtyStorage = make(Storage) + } } // updateTrie writes cached storage modifications into the object's storage trie. -func (self *stateObject) updateTrie(db Database) Trie { - tr := self.getTrie(db) - for key, value := range self.dirtyStorage { - delete(self.dirtyStorage, key) +func (s *stateObject) updateTrie(db Database) Trie { + // Make sure all dirty slots are finalized into the pending storage area + s.finalise() + // Track the amount of time wasted on updating the storge trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) + } + // Insert all the pending updates into the trie + tr := s.getTrie(db) + for key, value := range s.pendingStorage { // Skip noop changes, persist actual changes - if value == self.originStorage[key] { + if value == s.originStorage[key] { continue } - self.originStorage[key] = value + s.originStorage[key] = value if (value == common.Hash{}) { - self.setError(tr.TryDelete(key[:])) + s.setError(tr.TryDelete(key[:])) continue } // Encoding []byte cannot fail, ok to ignore the error. - v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) - self.setError(tr.TryUpdate(key[:], v)) + v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) + s.setError(tr.TryUpdate(key[:], v)) + } + if len(s.pendingStorage) > 0 { + s.pendingStorage = make(Storage) } return tr } // UpdateRoot sets the trie root to the current root hash of -func (self *stateObject) updateRoot(db Database) { - self.updateTrie(db) - self.data.Root = self.trie.Hash() +func (s *stateObject) updateRoot(db Database) { + s.updateTrie(db) + + // Track the amount of time wasted on hashing the storge trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) + } + s.data.Root = s.trie.Hash() } // CommitTrie the storage trie of the object to db. // This updates the trie root. -func (self *stateObject) CommitTrie(db Database) error { - self.updateTrie(db) - if self.dbErr != nil { - return self.dbErr +func (s *stateObject) CommitTrie(db Database) error { + s.updateTrie(db) + if s.dbErr != nil { + return s.dbErr } - root, err := self.trie.Commit(nil) + // Track the amount of time wasted on committing the storge trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) + } + root, err := s.trie.Commit(nil) if err == nil { - self.data.Root = root + s.data.Root = root } return err } // AddBalance removes amount from c's balance. // It is used to add funds to the destination account of a transfer. -func (c *stateObject) AddBalance(amount *big.Int) { +func (s *stateObject) AddBalance(amount *big.Int) { // EIP158: We must check emptiness for the objects such that the account // clearing (0,0,0 objects) can take effect. if amount.Sign() == 0 { - if c.empty() { - c.touch() + if s.empty() { + s.touch() } return } - c.SetBalance(new(big.Int).Add(c.Balance(), amount)) + s.SetBalance(new(big.Int).Add(s.Balance(), amount)) } // SubBalance removes amount from c's balance. // It is used to remove funds from the origin account of a transfer. -func (c *stateObject) SubBalance(amount *big.Int) { +func (s *stateObject) SubBalance(amount *big.Int) { if amount.Sign() == 0 { return } - c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) + s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) } -func (self *stateObject) SetBalance(amount *big.Int) { - self.db.journal.append(balanceChange{ - account: &self.address, - prev: new(big.Int).Set(self.data.Balance), +func (s *stateObject) SetBalance(amount *big.Int) { + s.db.journal.append(balanceChange{ + account: &s.address, + prev: new(big.Int).Set(s.data.Balance), }) - self.setBalance(amount) + s.setBalance(amount) } -func (self *stateObject) setBalance(amount *big.Int) { - self.data.Balance = amount +func (s *stateObject) setBalance(amount *big.Int) { + s.data.Balance = amount } // Return the gas back to the origin. Used by the Virtual machine or Closures -func (c *stateObject) ReturnGas(gas *big.Int) {} +func (s *stateObject) ReturnGas(gas *big.Int) {} -func (self *stateObject) deepCopy(db *StateDB) *stateObject { - stateObject := newObject(db, self.address, self.data) - if self.trie != nil { - stateObject.trie = db.db.CopyTrie(self.trie) +func (s *stateObject) deepCopy(db *StateDB) *stateObject { + stateObject := newObject(db, s.address, s.data) + if s.trie != nil { + stateObject.trie = db.db.CopyTrie(s.trie) } - stateObject.code = self.code - stateObject.dirtyStorage = self.dirtyStorage.Copy() - stateObject.originStorage = self.originStorage.Copy() - stateObject.suicided = self.suicided - stateObject.dirtyCode = self.dirtyCode - stateObject.deleted = self.deleted + stateObject.code = s.code + stateObject.dirtyStorage = s.dirtyStorage.Copy() + stateObject.originStorage = s.originStorage.Copy() + stateObject.pendingStorage = s.pendingStorage.Copy() + stateObject.suicided = s.suicided + stateObject.dirtyCode = s.dirtyCode + stateObject.deleted = s.deleted return stateObject } @@ -315,69 +391,69 @@ func (self *stateObject) deepCopy(db *StateDB) *stateObject { // // Returns the address of the contract/account -func (c *stateObject) Address() common.Address { - return c.address +func (s *stateObject) Address() common.Address { + return s.address } // Code returns the contract code associated with this object, if any. -func (self *stateObject) Code(db Database) []byte { - if self.code != nil { - return self.code +func (s *stateObject) Code(db Database) []byte { + if s.code != nil { + return s.code } - if bytes.Equal(self.CodeHash(), emptyCodeHash) { + if bytes.Equal(s.CodeHash(), emptyCodeHash) { return nil } - code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) + code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) if err != nil { - self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) + s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) } - self.code = code + s.code = code return code } -func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { - prevcode := self.Code(self.db.db) - self.db.journal.append(codeChange{ - account: &self.address, - prevhash: self.CodeHash(), +func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { + prevcode := s.Code(s.db.db) + s.db.journal.append(codeChange{ + account: &s.address, + prevhash: s.CodeHash(), prevcode: prevcode, }) - self.setCode(codeHash, code) + s.setCode(codeHash, code) } -func (self *stateObject) setCode(codeHash common.Hash, code []byte) { - self.code = code - self.data.CodeHash = codeHash[:] - self.dirtyCode = true +func (s *stateObject) setCode(codeHash common.Hash, code []byte) { + s.code = code + s.data.CodeHash = codeHash[:] + s.dirtyCode = true } -func (self *stateObject) SetNonce(nonce uint64) { - self.db.journal.append(nonceChange{ - account: &self.address, - prev: self.data.Nonce, +func (s *stateObject) SetNonce(nonce uint64) { + s.db.journal.append(nonceChange{ + account: &s.address, + prev: s.data.Nonce, }) - self.setNonce(nonce) + s.setNonce(nonce) } -func (self *stateObject) setNonce(nonce uint64) { - self.data.Nonce = nonce +func (s *stateObject) setNonce(nonce uint64) { + s.data.Nonce = nonce } -func (self *stateObject) CodeHash() []byte { - return self.data.CodeHash +func (s *stateObject) CodeHash() []byte { + return s.data.CodeHash } -func (self *stateObject) Balance() *big.Int { - return self.data.Balance +func (s *stateObject) Balance() *big.Int { + return s.data.Balance } -func (self *stateObject) Nonce() uint64 { - return self.data.Nonce +func (s *stateObject) Nonce() uint64 { + return s.data.Nonce } // Never called, but must be present to allow stateObject to be used // as a vm.Account interface that also satisfies the vm.ContractRef // interface. Interfaces are awesome. -func (self *stateObject) Value() *big.Int { +func (s *stateObject) Value() *big.Int { panic("Value on stateObject should never be called") } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go index 2230b10ef..9034d5533 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/statedb.go @@ -22,11 +22,13 @@ import ( "fmt" "math/big" "sort" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) @@ -37,8 +39,8 @@ type revision struct { } var ( - // emptyState is the known hash of an empty state trie entry. - emptyState = crypto.Keccak256Hash(nil) + // emptyRoot is the known root hash of an empty trie. + emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") // emptyCode is the known hash of the empty EVM bytecode. emptyCode = crypto.Keccak256Hash(nil) @@ -51,6 +53,10 @@ func (n *proofList) Put(key []byte, value []byte) error { return nil } +func (n *proofList) Delete(key []byte) error { + panic("not supported") +} + // StateDBs within the ethereum protocol are used to store anything // within the merkle trie. StateDBs take care of caching and storing // nested states. It's the general query interface to retrieve: @@ -61,8 +67,9 @@ type StateDB struct { trie Trie // This map holds 'live' objects, which will get modified while processing a state transition. - stateObjects map[common.Address]*stateObject - stateObjectsDirty map[common.Address]struct{} + stateObjects map[common.Address]*stateObject + stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie + stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution // DB error. // State objects are used by the consensus core and VM which are @@ -86,6 +93,16 @@ type StateDB struct { journal *journal validRevisions []revision nextRevisionId int + + // Measurements gathered during execution for debugging purposes + AccountReads time.Duration + AccountHashes time.Duration + AccountUpdates time.Duration + AccountCommits time.Duration + StorageReads time.Duration + StorageHashes time.Duration + StorageUpdates time.Duration + StorageCommits time.Duration } // Create a new state from a given trie. @@ -95,13 +112,14 @@ func New(root common.Hash, db Database) (*StateDB, error) { return nil, err } return &StateDB{ - db: db, - trie: tr, - stateObjects: make(map[common.Address]*stateObject), - stateObjectsDirty: make(map[common.Address]struct{}), - logs: make(map[common.Hash][]*types.Log), - preimages: make(map[common.Hash][]byte), - journal: newJournal(), + db: db, + trie: tr, + stateObjects: make(map[common.Address]*stateObject), + stateObjectsPending: make(map[common.Address]struct{}), + stateObjectsDirty: make(map[common.Address]struct{}), + logs: make(map[common.Hash][]*types.Log), + preimages: make(map[common.Hash][]byte), + journal: newJournal(), }, nil } @@ -125,6 +143,7 @@ func (self *StateDB) Reset(root common.Hash) error { } self.trie = tr self.stateObjects = make(map[common.Address]*stateObject) + self.stateObjectsPending = make(map[common.Address]struct{}) self.stateObjectsDirty = make(map[common.Address]struct{}) self.thash = common.Hash{} self.bhash = common.Hash{} @@ -221,6 +240,16 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 { return 0 } +// TxIndex returns the current transaction index set by Prepare. +func (self *StateDB) TxIndex() int { + return self.txIndex +} + +// BlockHash returns the current block hash set by Prepare. +func (self *StateDB) BlockHash() common.Hash { + return self.bhash +} + func (self *StateDB) GetCode(addr common.Address) []byte { stateObject := self.getStateObject(addr) if stateObject != nil { @@ -360,6 +389,15 @@ func (self *StateDB) SetState(addr common.Address, key, value common.Hash) { } } +// SetStorage replaces the entire storage for the specified account with given +// storage. This function should only be used for debugging. +func (self *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) { + stateObject := self.GetOrNewStateObject(addr) + if stateObject != nil { + stateObject.SetStorage(storage) + } +} + // Suicide marks the given account as suicided. // This clears the account balance. // @@ -386,36 +424,59 @@ func (self *StateDB) Suicide(addr common.Address) bool { // // updateStateObject writes the given object to the trie. -func (self *StateDB) updateStateObject(stateObject *stateObject) { - addr := stateObject.Address() - data, err := rlp.EncodeToBytes(stateObject) +func (s *StateDB) updateStateObject(obj *stateObject) { + // Track the amount of time wasted on updating the account from the trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) + } + // Encode the account and update the account trie + addr := obj.Address() + + data, err := rlp.EncodeToBytes(obj) if err != nil { panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) } - self.setError(self.trie.TryUpdate(addr[:], data)) + s.setError(s.trie.TryUpdate(addr[:], data)) } // deleteStateObject removes the given object from the state trie. -func (self *StateDB) deleteStateObject(stateObject *stateObject) { - stateObject.deleted = true - addr := stateObject.Address() - self.setError(self.trie.TryDelete(addr[:])) +func (s *StateDB) deleteStateObject(obj *stateObject) { + // Track the amount of time wasted on deleting the account from the trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) + } + // Delete the account from the trie + addr := obj.Address() + s.setError(s.trie.TryDelete(addr[:])) } -// Retrieve a state object given by the address. Returns nil if not found. -func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { - // Prefer 'live' objects. - if obj := self.stateObjects[addr]; obj != nil { - if obj.deleted { - return nil - } +// getStateObject retrieves a state object given by the address, returning nil if +// the object is not found or was deleted in this execution context. If you need +// to differentiate between non-existent/just-deleted, use getDeletedStateObject. +func (s *StateDB) getStateObject(addr common.Address) *stateObject { + if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { return obj } + return nil +} - // Load the object from the database. - enc, err := self.trie.TryGet(addr[:]) +// getDeletedStateObject is similar to getStateObject, but instead of returning +// nil for a deleted state object, it returns the actual object with the deleted +// flag set. This is needed by the state journal to revert to the correct self- +// destructed object instead of wiping all knowledge about the state object. +func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { + // Prefer live objects if any is available + if obj := s.stateObjects[addr]; obj != nil { + return obj + } + // Track the amount of time wasted on loading the object from the database + if metrics.EnabledExpensive { + defer func(start time.Time) { s.AccountReads += time.Since(start) }(time.Now()) + } + // Load the object from the database + enc, err := s.trie.TryGet(addr[:]) if len(enc) == 0 { - self.setError(err) + s.setError(err) return nil } var data Account @@ -423,9 +484,9 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje log.Error("Failed to decode state object", "addr", addr, "err", err) return nil } - // Insert into the live set. - obj := newObject(self, addr, data) - self.setStateObject(obj) + // Insert into the live set + obj := newObject(s, addr, data) + s.setStateObject(obj) return obj } @@ -436,7 +497,7 @@ func (self *StateDB) setStateObject(object *stateObject) { // Retrieve a state object or create a new state object if nil. func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { stateObject := self.getStateObject(addr) - if stateObject == nil || stateObject.deleted { + if stateObject == nil { stateObject, _ = self.createObject(addr) } return stateObject @@ -445,7 +506,8 @@ func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { // createObject creates a new state object. If there is an existing account with // the given address, it is overwritten and returned as the second return value. func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { - prev = self.getStateObject(addr) + prev = self.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! + newobj = newObject(self, addr, Account{}) newobj.setNonce(0) // sets the object to dirty if prev == nil { @@ -474,20 +536,33 @@ func (self *StateDB) CreateAccount(addr common.Address) { } } -func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) { +func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { so := db.getStateObject(addr) if so == nil { - return + return nil } it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil)) + for it.Next() { key := common.BytesToHash(db.trie.GetKey(it.Key)) if value, dirty := so.dirtyStorage[key]; dirty { - cb(key, value) + if !cb(key, value) { + return nil + } continue } - cb(key, common.BytesToHash(it.Value)) + + if len(it.Value) > 0 { + _, content, _, err := rlp.Split(it.Value) + if err != nil { + return err + } + if !cb(key, common.BytesToHash(content)) { + return nil + } + } } + return nil } // Copy creates a deep, independent copy of the state. @@ -495,15 +570,16 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common func (self *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ - db: self.db, - trie: self.db.CopyTrie(self.trie), - stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), - stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), - refund: self.refund, - logs: make(map[common.Hash][]*types.Log, len(self.logs)), - logSize: self.logSize, - preimages: make(map[common.Hash][]byte), - journal: newJournal(), + db: self.db, + trie: self.db.CopyTrie(self.trie), + stateObjects: make(map[common.Address]*stateObject, len(self.journal.dirties)), + stateObjectsPending: make(map[common.Address]struct{}, len(self.stateObjectsPending)), + stateObjectsDirty: make(map[common.Address]struct{}, len(self.journal.dirties)), + refund: self.refund, + logs: make(map[common.Hash][]*types.Log, len(self.logs)), + logSize: self.logSize, + preimages: make(map[common.Hash][]byte, len(self.preimages)), + journal: newJournal(), } // Copy the dirty states, logs, and preimages for addr := range self.journal.dirties { @@ -519,11 +595,17 @@ func (self *StateDB) Copy() *StateDB { // Above, we don't copy the actual journal. This means that if the copy is copied, the // loop above will be a no-op, since the copy's journal is empty. // Thus, here we iterate over stateObjects, to enable copies of copies + for addr := range self.stateObjectsPending { + if _, exist := state.stateObjects[addr]; !exist { + state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) + } + state.stateObjectsPending[addr] = struct{}{} + } for addr := range self.stateObjectsDirty { if _, exist := state.stateObjects[addr]; !exist { state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state) - state.stateObjectsDirty[addr] = struct{}{} } + state.stateObjectsDirty[addr] = struct{}{} } for hash, logs := range self.logs { cpy := make([]*types.Log, len(logs)) @@ -568,11 +650,12 @@ func (self *StateDB) GetRefund() uint64 { return self.refund } -// Finalise finalises the state by removing the self destructed objects -// and clears the journal as well as the refunds. +// Finalise finalises the state by removing the self destructed objects and clears +// the journal as well as the refunds. Finalise, however, will not push any updates +// into the tries just yet. Only IntermediateRoot or Commit will do that. func (s *StateDB) Finalise(deleteEmptyObjects bool) { for addr := range s.journal.dirties { - stateObject, exist := s.stateObjects[addr] + obj, exist := s.stateObjects[addr] if !exist { // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the @@ -582,13 +665,12 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // Thus, we can safely ignore it here continue } - - if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) { - s.deleteStateObject(stateObject) + if obj.suicided || (deleteEmptyObjects && obj.empty()) { + obj.deleted = true } else { - stateObject.updateRoot(s.db) - s.updateStateObject(stateObject) + obj.finalise() } + s.stateObjectsPending[addr] = struct{}{} s.stateObjectsDirty[addr] = struct{}{} } // Invalidate journal because reverting across transactions is not allowed. @@ -599,7 +681,25 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // It is called in between transactions to get the root hash that // goes into transaction receipts. func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { + // Finalise all the dirty storage states and write them into the tries s.Finalise(deleteEmptyObjects) + + for addr := range s.stateObjectsPending { + obj := s.stateObjects[addr] + if obj.deleted { + s.deleteStateObject(obj) + } else { + obj.updateRoot(s.db) + s.updateStateObject(obj) + } + } + if len(s.stateObjectsPending) > 0 { + s.stateObjectsPending = make(map[common.Address]struct{}) + } + // Track the amount of time wasted on hashing the account trie + if metrics.EnabledExpensive { + defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now()) + } return s.trie.Hash() } @@ -612,48 +712,45 @@ func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) { } func (s *StateDB) clearJournalAndRefund() { - s.journal = newJournal() - s.validRevisions = s.validRevisions[:0] - s.refund = 0 + if len(s.journal.entries) > 0 { + s.journal = newJournal() + s.refund = 0 + } + s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entires } // Commit writes the state to the underlying in-memory trie database. -func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) { - defer s.clearJournalAndRefund() +func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { + // Finalize any pending changes and merge everything into the tries + s.IntermediateRoot(deleteEmptyObjects) - for addr := range s.journal.dirties { - s.stateObjectsDirty[addr] = struct{}{} - } - // Commit objects to the trie. - for addr, stateObject := range s.stateObjects { - _, isDirty := s.stateObjectsDirty[addr] - switch { - case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()): - // If the object has been removed, don't bother syncing it - // and just mark it for deletion in the trie. - s.deleteStateObject(stateObject) - case isDirty: + // Commit objects to the trie, measuring the elapsed time + for addr := range s.stateObjectsDirty { + if obj := s.stateObjects[addr]; !obj.deleted { // Write any contract code associated with the state object - if stateObject.code != nil && stateObject.dirtyCode { - s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code) - stateObject.dirtyCode = false + if obj.code != nil && obj.dirtyCode { + s.db.TrieDB().InsertBlob(common.BytesToHash(obj.CodeHash()), obj.code) + obj.dirtyCode = false } - // Write any storage changes in the state object to its storage trie. - if err := stateObject.CommitTrie(s.db); err != nil { + // Write any storage changes in the state object to its storage trie + if err := obj.CommitTrie(s.db); err != nil { return common.Hash{}, err } - // Update the object in the main account trie. - s.updateStateObject(stateObject) } - delete(s.stateObjectsDirty, addr) } - // Write trie changes. - root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { + if len(s.stateObjectsDirty) > 0 { + s.stateObjectsDirty = make(map[common.Address]struct{}) + } + // Write the account trie changes, measuing the amount of wasted time + if metrics.EnabledExpensive { + defer func(start time.Time) { s.AccountCommits += time.Since(start) }(time.Now()) + } + return s.trie.Commit(func(leaf []byte, parent common.Hash) error { var account Account if err := rlp.DecodeBytes(leaf, &account); err != nil { return nil } - if account.Root != emptyState { + if account.Root != emptyRoot { s.db.TrieDB().Reference(account.Root, parent) } code := common.BytesToHash(account.CodeHash) @@ -662,6 +759,4 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) } return nil }) - log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads()) - return root, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state/sync.go b/vendor/github.com/ethereum/go-ethereum/core/state/sync.go index c566e7907..ef7930527 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state/sync.go @@ -20,12 +20,13 @@ import ( "bytes" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) // NewStateSync create a new state trie download scheduler. -func NewStateSync(root common.Hash, database trie.DatabaseReader) *trie.Sync { +func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.SyncBloom) *trie.Sync { var syncer *trie.Sync callback := func(leaf []byte, parent common.Hash) error { var obj Account @@ -36,6 +37,6 @@ func NewStateSync(root common.Hash, database trie.DatabaseReader) *trie.Sync { syncer.AddRawEntry(common.BytesToHash(obj.CodeHash), 64, parent) return nil } - syncer = trie.NewSync(root, database, callback) + syncer = trie.NewSync(root, database, callback, bloom) return syncer } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state_prefetcher.go b/vendor/github.com/ethereum/go-ethereum/core/state_prefetcher.go new file mode 100644 index 000000000..cb85a05b5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/state_prefetcher.go @@ -0,0 +1,85 @@ +// Copyright 2019 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 core + +import ( + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "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/params" +) + +// statePrefetcher is a basic Prefetcher, which blindly executes a block on top +// of an arbitrary state with the goal of prefetching potentially useful state +// data from disk before the main block processor start executing. +type statePrefetcher struct { + config *params.ChainConfig // Chain configuration options + bc *BlockChain // Canonical block chain + engine consensus.Engine // Consensus engine used for block rewards +} + +// newStatePrefetcher initialises a new statePrefetcher. +func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *statePrefetcher { + return &statePrefetcher{ + config: config, + bc: bc, + engine: engine, + } +} + +// Prefetch processes the state changes according to the Ethereum rules by running +// the transaction messages using the statedb, but any changes are discarded. The +// only goal is to pre-cache transaction signatures and state trie nodes. +func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) { + var ( + header = block.Header() + gaspool = new(GasPool).AddGas(block.GasLimit()) + ) + // Iterate over and process the individual transactions + for i, tx := range block.Transactions() { + // If block precaching was interrupted, abort + if interrupt != nil && atomic.LoadUint32(interrupt) == 1 { + return + } + // Block precaching permitted to continue, execute the transaction + statedb.Prepare(tx.Hash(), block.Hash(), i) + if err := precacheTransaction(p.config, p.bc, nil, gaspool, statedb, header, tx, cfg); err != nil { + return // Ugh, something went horribly wrong, bail out + } + } +} + +// precacheTransaction attempts to apply a transaction to the given state database +// and uses the input parameters for its environment. The goal is not to execute +// the transaction successfully, rather to warm up touched data slots. +func precacheTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gaspool *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, cfg vm.Config) error { + // Convert the transaction into an executable message and pre-cache its sender + msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) + if err != nil { + return err + } + // Create the EVM and execute the transaction + context := NewEVMContext(msg, header, bc, author) + vm := vm.NewEVM(context, statedb, config, cfg) + + _, _, _, err = ApplyMessage(vm, msg, gaspool) + return err +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/state_processor.go b/vendor/github.com/ethereum/go-ethereum/core/state_processor.go index 503a35d16..cfe17d587 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state_processor.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state_processor.go @@ -68,7 +68,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Iterate over and process the individual transactions for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) - receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) + receipt, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) if err != nil { return nil, nil, 0, err } @@ -76,7 +76,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs = append(allLogs, receipt.Logs...) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts) + p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles()) return receipts, allLogs, *usedGas, nil } @@ -85,10 +85,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { - return nil, 0, err + return nil, err } // Create a new context to be used in the EVM environment context := NewEVMContext(msg, header, bc, author) @@ -98,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Apply the transaction to the current state (included in the env) _, gas, failed, err := ApplyMessage(vmenv, msg, gp) if err != nil { - return nil, 0, err + return nil, err } // Update the state with pending changes var root []byte @@ -121,6 +121,9 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Set the receipt logs and create a bloom for filtering receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.BlockHash = statedb.BlockHash() + receipt.BlockNumber = header.Number + receipt.TransactionIndex = uint(statedb.TxIndex()) - return receipt, gas, err + return receipt, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/state_transition.go b/vendor/github.com/ethereum/go-ethereum/core/state_transition.go index fda081b7d..bef6e9b0e 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/state_transition.go +++ b/vendor/github.com/ethereum/go-ethereum/core/state_transition.go @@ -76,10 +76,10 @@ type Message interface { } // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. -func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) { +func IntrinsicGas(data []byte, contractCreation, isEIP155 bool, isEIP2028 bool) (uint64, error) { // Set the starting gas for the raw transaction var gas uint64 - if contractCreation && homestead { + if contractCreation && isEIP155 { gas = params.TxGasContractCreation } else { gas = params.TxGas @@ -94,10 +94,14 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) } } // Make sure we don't exceed uint64 for all data combinations - if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz { + nonZeroGas := params.TxDataNonZeroGasFrontier + if isEIP2028 { + nonZeroGas = params.TxDataNonZeroGasEIP2028 + } + if (math.MaxUint64-gas)/nonZeroGas < nz { return 0, vm.ErrOutOfGas } - gas += nz * params.TxDataNonZeroGas + gas += nz * nonZeroGas z := uint64(len(data)) - nz if (math.MaxUint64-gas)/params.TxDataZeroGas < z { @@ -187,10 +191,11 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo msg := st.msg sender := vm.AccountRef(msg.From()) homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber) + istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.BlockNumber) contractCreation := msg.To() == nil // Pay intrinsic gas - gas, err := IntrinsicGas(st.data, contractCreation, homestead) + gas, err := IntrinsicGas(st.data, contractCreation, homestead, istanbul) if err != nil { return nil, 0, false, err } diff --git a/vendor/github.com/ethereum/go-ethereum/core/tx_list.go b/vendor/github.com/ethereum/go-ethereum/core/tx_list.go index 57abc5148..75bfdaeda 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/tx_list.go +++ b/vendor/github.com/ethereum/go-ethereum/core/tx_list.go @@ -418,9 +418,9 @@ func (l *txPricedList) Put(tx *types.Transaction) { // Removed notifies the prices transaction list that an old transaction dropped // from the pool. The list will just keep a counter of stale objects and update // the heap if a large enough ratio of transactions go stale. -func (l *txPricedList) Removed() { +func (l *txPricedList) Removed(count int) { // Bump the stale counter, but exit if still too low (< 25%) - l.stales++ + l.stales += count if l.stales <= len(*l.items)/4 { return } diff --git a/vendor/github.com/ethereum/go-ethereum/core/tx_noncer.go b/vendor/github.com/ethereum/go-ethereum/core/tx_noncer.go new file mode 100644 index 000000000..aa87c643a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/tx_noncer.go @@ -0,0 +1,79 @@ +// Copyright 2019 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 core + +import ( + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" +) + +// txNoncer is a tiny virtual state database to manage the executable nonces of +// accounts in the pool, falling back to reading from a real state database if +// an account is unknown. +type txNoncer struct { + fallback *state.StateDB + nonces map[common.Address]uint64 + lock sync.Mutex +} + +// newTxNoncer creates a new virtual state database to track the pool nonces. +func newTxNoncer(statedb *state.StateDB) *txNoncer { + return &txNoncer{ + fallback: statedb.Copy(), + nonces: make(map[common.Address]uint64), + } +} + +// get returns the current nonce of an account, falling back to a real state +// database if the account is unknown. +func (txn *txNoncer) get(addr common.Address) uint64 { + // We use mutex for get operation is the underlying + // state will mutate db even for read access. + txn.lock.Lock() + defer txn.lock.Unlock() + + if _, ok := txn.nonces[addr]; !ok { + txn.nonces[addr] = txn.fallback.GetNonce(addr) + } + return txn.nonces[addr] +} + +// set inserts a new virtual nonce into the virtual state database to be returned +// whenever the pool requests it instead of reaching into the real state database. +func (txn *txNoncer) set(addr common.Address, nonce uint64) { + txn.lock.Lock() + defer txn.lock.Unlock() + + txn.nonces[addr] = nonce +} + +// setIfLower updates a new virtual nonce into the virtual state database if the +// the new one is lower. +func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) { + txn.lock.Lock() + defer txn.lock.Unlock() + + if _, ok := txn.nonces[addr]; !ok { + txn.nonces[addr] = txn.fallback.GetNonce(addr) + } + if txn.nonces[addr] <= nonce { + return + } + txn.nonces[addr] = nonce +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go index 552d3692b..f7032dbd1 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go +++ b/vendor/github.com/ethereum/go-ethereum/core/tx_pool.go @@ -85,20 +85,26 @@ var ( var ( // Metrics for the pending pool - pendingDiscardCounter = metrics.NewRegisteredCounter("txpool/pending/discard", nil) - pendingReplaceCounter = metrics.NewRegisteredCounter("txpool/pending/replace", nil) - pendingRateLimitCounter = metrics.NewRegisteredCounter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting - pendingNofundsCounter = metrics.NewRegisteredCounter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds + pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil) + pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil) + pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting + pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds // Metrics for the queued pool - queuedDiscardCounter = metrics.NewRegisteredCounter("txpool/queued/discard", nil) - queuedReplaceCounter = metrics.NewRegisteredCounter("txpool/queued/replace", nil) - queuedRateLimitCounter = metrics.NewRegisteredCounter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting - queuedNofundsCounter = metrics.NewRegisteredCounter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds + queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil) + queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil) + queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting + queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds // General tx metrics - invalidTxCounter = metrics.NewRegisteredCounter("txpool/invalid", nil) - underpricedTxCounter = metrics.NewRegisteredCounter("txpool/underpriced", nil) + knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil) + validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil) + invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) + underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) + + pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) + queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) + localGauge = metrics.NewRegisteredGauge("txpool/local", nil) ) // TxStatus is the current status of a transaction as seen by the pool. @@ -203,20 +209,20 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig { // current state) and future transactions. Transactions move between those // two states over time as they are received and processed. type TxPool struct { - config TxPoolConfig - chainconfig *params.ChainConfig - chain blockChain - gasPrice *big.Int - txFeed event.Feed - scope event.SubscriptionScope - chainHeadCh chan ChainHeadEvent - chainHeadSub event.Subscription - signer types.Signer - mu sync.RWMutex + config TxPoolConfig + chainconfig *params.ChainConfig + chain blockChain + gasPrice *big.Int + txFeed event.Feed + scope event.SubscriptionScope + signer types.Signer + mu sync.RWMutex - currentState *state.StateDB // Current state in the blockchain head - pendingState *state.ManagedState // Pending state tracking virtual nonces - currentMaxGas uint64 // Current gas limit for transaction caps + istanbul bool // Fork indicator whether we are in the istanbul stage. + + currentState *state.StateDB // Current state in the blockchain head + pendingNonces *txNoncer // Pending state tracking virtual nonces + currentMaxGas uint64 // Current gas limit for transaction caps locals *accountSet // Set of local transaction to exempt from eviction rules journal *txJournal // Journal of local transaction to back up to disk @@ -227,9 +233,18 @@ type TxPool struct { all *txLookup // All transactions to allow lookups priced *txPricedList // All transactions sorted by price - wg sync.WaitGroup // for shutdown sync + chainHeadCh chan ChainHeadEvent + chainHeadSub event.Subscription + reqResetCh chan *txpoolResetRequest + reqPromoteCh chan *accountSet + queueTxEventCh chan *types.Transaction + reorgDoneCh chan chan struct{} + reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop + wg sync.WaitGroup // tracks loop, scheduleReorgLoop +} - homestead bool +type txpoolResetRequest struct { + oldHead, newHead *types.Header } // NewTxPool creates a new transaction pool to gather, sort and filter inbound @@ -240,16 +255,21 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block // Create the transaction pool with its initial settings pool := &TxPool{ - config: config, - chainconfig: chainconfig, - chain: chain, - signer: types.NewEIP155Signer(chainconfig.ChainID), - pending: make(map[common.Address]*txList), - queue: make(map[common.Address]*txList), - beats: make(map[common.Address]time.Time), - all: newTxLookup(), - chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), - gasPrice: new(big.Int).SetUint64(config.PriceLimit), + config: config, + chainconfig: chainconfig, + chain: chain, + signer: types.NewEIP155Signer(chainconfig.ChainID), + pending: make(map[common.Address]*txList), + queue: make(map[common.Address]*txList), + beats: make(map[common.Address]time.Time), + all: newTxLookup(), + chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), + reqResetCh: make(chan *txpoolResetRequest), + reqPromoteCh: make(chan *accountSet), + queueTxEventCh: make(chan *types.Transaction), + reorgDoneCh: make(chan chan struct{}), + reorgShutdownCh: make(chan struct{}), + gasPrice: new(big.Int).SetUint64(config.PriceLimit), } pool.locals = newAccountSet(pool.signer) for _, addr := range config.Locals { @@ -259,6 +279,10 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block pool.priced = newTxPricedList(pool.all) pool.reset(nil, chain.CurrentBlock().Header()) + // Start the reorg loop early so it can handle requests generated during journal loading. + pool.wg.Add(1) + go pool.scheduleReorgLoop() + // If local transactions and journaling is enabled, load from disk if !config.NoLocals && config.Journal != "" { pool.journal = newTxJournal(config.Journal) @@ -270,10 +294,9 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block log.Warn("Failed to rotate transaction journal", "err", err) } } - // Subscribe events from blockchain - pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) - // Start the event loop and return + // Subscribe events from blockchain and start the main event loop. + pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) pool.wg.Add(1) go pool.loop() @@ -286,38 +309,31 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block func (pool *TxPool) loop() { defer pool.wg.Done() - // Start the stats reporting and transaction eviction tickers - var prevPending, prevQueued, prevStales int - - report := time.NewTicker(statsReportInterval) + var ( + prevPending, prevQueued, prevStales int + // Start the stats reporting and transaction eviction tickers + report = time.NewTicker(statsReportInterval) + evict = time.NewTicker(evictionInterval) + journal = time.NewTicker(pool.config.Rejournal) + // Track the previous head headers for transaction reorgs + head = pool.chain.CurrentBlock() + ) defer report.Stop() - - evict := time.NewTicker(evictionInterval) defer evict.Stop() - - journal := time.NewTicker(pool.config.Rejournal) defer journal.Stop() - // Track the previous head headers for transaction reorgs - head := pool.chain.CurrentBlock() - - // Keep waiting for and reacting to the various events for { select { // Handle ChainHeadEvent case ev := <-pool.chainHeadCh: if ev.Block != nil { - pool.mu.Lock() - if pool.chainconfig.IsHomestead(ev.Block.Number()) { - pool.homestead = true - } - pool.reset(head.Header(), ev.Block.Header()) + pool.requestReset(head.Header(), ev.Block.Header()) head = ev.Block - - pool.mu.Unlock() } - // Be unsubscribed due to system stopped + + // System shutdown. case <-pool.chainHeadSub.Err(): + close(pool.reorgShutdownCh) return // Handle stats reporting ticks @@ -362,99 +378,6 @@ func (pool *TxPool) loop() { } } -// lockedReset is a wrapper around reset to allow calling it in a thread safe -// manner. This method is only ever used in the tester! -func (pool *TxPool) lockedReset(oldHead, newHead *types.Header) { - pool.mu.Lock() - defer pool.mu.Unlock() - - pool.reset(oldHead, newHead) -} - -// reset retrieves the current state of the blockchain and ensures the content -// of the transaction pool is valid with regard to the chain state. -func (pool *TxPool) reset(oldHead, newHead *types.Header) { - // If we're reorging an old state, reinject all dropped transactions - var reinject types.Transactions - - if oldHead != nil && oldHead.Hash() != newHead.ParentHash { - // If the reorg is too deep, avoid doing it (will happen during fast sync) - oldNum := oldHead.Number.Uint64() - newNum := newHead.Number.Uint64() - - if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { - log.Debug("Skipping deep transaction reorg", "depth", depth) - } else { - // Reorg seems shallow enough to pull in all transactions into memory - var discarded, included types.Transactions - - var ( - rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) - add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) - ) - for rem.NumberU64() > add.NumberU64() { - discarded = append(discarded, rem.Transactions()...) - if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) - return - } - } - for add.NumberU64() > rem.NumberU64() { - included = append(included, add.Transactions()...) - if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) - return - } - } - for rem.Hash() != add.Hash() { - discarded = append(discarded, rem.Transactions()...) - if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) - return - } - included = append(included, add.Transactions()...) - if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) - return - } - } - reinject = types.TxDifference(discarded, included) - } - } - // Initialize the internal state to the current head - if newHead == nil { - newHead = pool.chain.CurrentBlock().Header() // Special case during testing - } - statedb, err := pool.chain.StateAt(newHead.Root) - if err != nil { - log.Error("Failed to reset txpool state", "err", err) - return - } - pool.currentState = statedb - pool.pendingState = state.ManageState(statedb) - pool.currentMaxGas = newHead.GasLimit - - // Inject any transactions discarded due to reorgs - log.Debug("Reinjecting stale transactions", "count", len(reinject)) - senderCacher.recover(pool.signer, reinject) - pool.addTxsLocked(reinject, false) - - // validate the pool of pending transactions, this will remove - // any transactions that have been included in the block or - // have been invalidated because of another transaction (e.g. - // higher gas price) - pool.demoteUnexecutables() - - // Update all accounts to the latest known pending nonce - for addr, list := range pool.pending { - txs := list.Flatten() // Heavy but will be cached and is needed by the miner anyway - pool.pendingState.SetNonce(addr, txs[len(txs)-1].Nonce()+1) - } - // Check the queue and move transactions over to the pending if possible - // or remove those that have become invalid - pool.promoteExecutables(nil) -} - // Stop terminates the transaction pool. func (pool *TxPool) Stop() { // Unsubscribe all subscriptions registered from txpool @@ -497,12 +420,13 @@ func (pool *TxPool) SetGasPrice(price *big.Int) { log.Info("Transaction pool price threshold updated", "price", price) } -// State returns the virtual managed state of the transaction pool. -func (pool *TxPool) State() *state.ManagedState { +// Nonce returns the next nonce of an account, with all transactions executable +// by the pool already applied on top. +func (pool *TxPool) Nonce(addr common.Address) uint64 { pool.mu.RLock() defer pool.mu.RUnlock() - return pool.pendingState + return pool.pendingNonces.get(addr) } // Stats retrieves the current pool stats, namely the number of pending and the @@ -618,7 +542,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { return ErrInsufficientFunds } - intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) + // Ensure the transaction has more gas than the basic tx fee. + intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, true, pool.istanbul) if err != nil { return err } @@ -628,25 +553,25 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { return nil } -// add validates a transaction and inserts it into the non-executable queue for -// later pending promotion and execution. If the transaction is a replacement for -// an already pending or queued one, it overwrites the previous and returns this -// so outer code doesn't uselessly call promote. +// add validates a transaction and inserts it into the non-executable queue for later +// pending promotion and execution. If the transaction is a replacement for an already +// pending or queued one, it overwrites the previous transaction if its price is higher. // // If a newly added transaction is marked as local, its sending account will be -// whitelisted, preventing any associated transaction from being dropped out of -// the pool due to pricing constraints. -func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { +// whitelisted, preventing any associated transaction from being dropped out of the pool +// due to pricing constraints. +func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) { // If the transaction is already known, discard it hash := tx.Hash() if pool.all.Get(hash) != nil { log.Trace("Discarding already known transaction", "hash", hash) + knownTxMeter.Mark(1) return false, fmt.Errorf("known transaction: %x", hash) } // If the transaction fails basic validation, discard it if err := pool.validateTx(tx, local); err != nil { log.Trace("Discarding invalid transaction", "hash", hash, "err", err) - invalidTxCounter.Inc(1) + invalidTxMeter.Mark(1) return false, err } // If the transaction pool is full, discard underpriced transactions @@ -654,45 +579,41 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { // If the new transaction is underpriced, don't accept it if !local && pool.priced.Underpriced(tx, pool.locals) { log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice()) - underpricedTxCounter.Inc(1) + underpricedTxMeter.Mark(1) return false, ErrUnderpriced } // New transaction is better than our worse ones, make room for it drop := pool.priced.Discard(pool.all.Count()-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals) for _, tx := range drop { log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "price", tx.GasPrice()) - underpricedTxCounter.Inc(1) + underpricedTxMeter.Mark(1) pool.removeTx(tx.Hash(), false) } } - // If the transaction is replacing an already pending one, do directly + // Try to replace an existing transaction in the pending pool from, _ := types.Sender(pool.signer, tx) // already validated if list := pool.pending[from]; list != nil && list.Overlaps(tx) { // Nonce already pending, check if required price bump is met inserted, old := list.Add(tx, pool.config.PriceBump) if !inserted { - pendingDiscardCounter.Inc(1) + pendingDiscardMeter.Mark(1) return false, ErrReplaceUnderpriced } // New transaction is better, replace old one if old != nil { pool.all.Remove(old.Hash()) - pool.priced.Removed() - pendingReplaceCounter.Inc(1) + pool.priced.Removed(1) + pendingReplaceMeter.Mark(1) } pool.all.Add(tx) pool.priced.Put(tx) pool.journalTx(from, tx) - + pool.queueTxEvent(tx) log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) - - // We've directly injected a replacement transaction, notify subsystems - go pool.txFeed.Send(NewTxsEvent{types.Transactions{tx}}) - return old != nil, nil } // New transaction isn't replacing a pending one, push into queue - replace, err := pool.enqueueTx(hash, tx) + replaced, err = pool.enqueueTx(hash, tx) if err != nil { return false, err } @@ -703,10 +624,13 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { pool.locals.add(from) } } + if local || pool.locals.contains(from) { + localGauge.Inc(1) + } pool.journalTx(from, tx) log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To()) - return replace, nil + return replaced, nil } // enqueueTx inserts a new transaction into the non-executable transaction queue. @@ -721,14 +645,17 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, er inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) if !inserted { // An older transaction was better, discard this - queuedDiscardCounter.Inc(1) + queuedDiscardMeter.Mark(1) return false, ErrReplaceUnderpriced } // Discard any previous transaction and mark this if old != nil { pool.all.Remove(old.Hash()) - pool.priced.Removed() - queuedReplaceCounter.Inc(1) + pool.priced.Removed(1) + queuedReplaceMeter.Mark(1) + } else { + // Nothing was replaced, bump the queued counter + queuedGauge.Inc(1) } if pool.all.Get(hash) == nil { pool.all.Add(tx) @@ -764,17 +691,20 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T if !inserted { // An older transaction was better, discard this pool.all.Remove(hash) - pool.priced.Removed() + pool.priced.Removed(1) - pendingDiscardCounter.Inc(1) + pendingDiscardMeter.Mark(1) return false } // Otherwise discard any previous transaction and mark this if old != nil { pool.all.Remove(old.Hash()) - pool.priced.Removed() + pool.priced.Removed(1) - pendingReplaceCounter.Inc(1) + pendingReplaceMeter.Mark(1) + } else { + // Nothing was replaced, bump the pending counter + pendingGauge.Inc(1) } // Failsafe to work around direct pending inserts (tests) if pool.all.Get(hash) == nil { @@ -783,112 +713,140 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T } // Set the potentially new pending nonce and notify any subsystems of the new tx pool.beats[addr] = time.Now() - pool.pendingState.SetNonce(addr, tx.Nonce()+1) + pool.pendingNonces.set(addr, tx.Nonce()+1) return true } -// AddLocal enqueues a single transaction into the pool if it is valid, marking -// the sender as a local one in the mean time, ensuring it goes around the local -// pricing constraints. -func (pool *TxPool) AddLocal(tx *types.Transaction) error { - return pool.addTx(tx, !pool.config.NoLocals) -} - -// AddRemote enqueues a single transaction into the pool if it is valid. If the -// sender is not among the locally tracked ones, full pricing constraints will -// apply. -func (pool *TxPool) AddRemote(tx *types.Transaction) error { - return pool.addTx(tx, false) -} - -// AddLocals enqueues a batch of transactions into the pool if they are valid, -// marking the senders as a local ones in the mean time, ensuring they go around -// the local pricing constraints. +// AddLocals enqueues a batch of transactions into the pool if they are valid, marking the +// senders as a local ones, ensuring they go around the local pricing constraints. +// +// This method is used to add transactions from the RPC API and performs synchronous pool +// reorganization and event propagation. func (pool *TxPool) AddLocals(txs []*types.Transaction) []error { - return pool.addTxs(txs, !pool.config.NoLocals) + return pool.addTxs(txs, !pool.config.NoLocals, true) } -// AddRemotes enqueues a batch of transactions into the pool if they are valid. -// If the senders are not among the locally tracked ones, full pricing constraints -// will apply. +// AddLocal enqueues a single local transaction into the pool if it is valid. This is +// a convenience wrapper aroundd AddLocals. +func (pool *TxPool) AddLocal(tx *types.Transaction) error { + errs := pool.AddLocals([]*types.Transaction{tx}) + return errs[0] +} + +// AddRemotes enqueues a batch of transactions into the pool if they are valid. If the +// senders are not among the locally tracked ones, full pricing constraints will apply. +// +// This method is used to add transactions from the p2p network and does not wait for pool +// reorganization and internal event propagation. func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error { - return pool.addTxs(txs, false) + return pool.addTxs(txs, false, false) } -// addTx enqueues a single transaction into the pool if it is valid. -func (pool *TxPool) addTx(tx *types.Transaction, local bool) error { - pool.mu.Lock() - defer pool.mu.Unlock() +// This is like AddRemotes, but waits for pool reorganization. Tests use this method. +func (pool *TxPool) AddRemotesSync(txs []*types.Transaction) []error { + return pool.addTxs(txs, false, true) +} - // Try to inject the transaction and update any state - replace, err := pool.add(tx, local) - if err != nil { - return err - } - // If we added a new transaction, run promotion checks and return - if !replace { - from, _ := types.Sender(pool.signer, tx) // already validated - pool.promoteExecutables([]common.Address{from}) - } - return nil +// This is like AddRemotes with a single transaction, but waits for pool reorganization. Tests use this method. +func (pool *TxPool) addRemoteSync(tx *types.Transaction) error { + errs := pool.AddRemotesSync([]*types.Transaction{tx}) + return errs[0] +} + +// AddRemote enqueues a single transaction into the pool if it is valid. This is a convenience +// wrapper around AddRemotes. +// +// Deprecated: use AddRemotes +func (pool *TxPool) AddRemote(tx *types.Transaction) error { + errs := pool.AddRemotes([]*types.Transaction{tx}) + return errs[0] } // addTxs attempts to queue a batch of transactions if they are valid. -func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) []error { - pool.mu.Lock() - defer pool.mu.Unlock() - - return pool.addTxsLocked(txs, local) -} - -// addTxsLocked attempts to queue a batch of transactions if they are valid, -// whilst assuming the transaction pool lock is already held. -func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) []error { - // Add the batch of transactions, tracking the accepted ones - dirty := make(map[common.Address]struct{}) - errs := make([]error, len(txs)) - +func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { + // Filter out known ones without obtaining the pool lock or recovering signatures + var ( + errs = make([]error, len(txs)) + news = make([]*types.Transaction, 0, len(txs)) + ) for i, tx := range txs { - var replace bool - if replace, errs[i] = pool.add(tx, local); errs[i] == nil && !replace { - from, _ := types.Sender(pool.signer, tx) // already validated - dirty[from] = struct{}{} + // If the transaction is known, pre-set the error slot + if pool.all.Get(tx.Hash()) != nil { + errs[i] = fmt.Errorf("known transaction: %x", tx.Hash()) + knownTxMeter.Mark(1) + continue } + // Accumulate all unknown transactions for deeper processing + news = append(news, tx) } - // Only reprocess the internal state if something was actually added - if len(dirty) > 0 { - addrs := make([]common.Address, 0, len(dirty)) - for addr := range dirty { - addrs = append(addrs, addr) + if len(news) == 0 { + return errs + } + // Cache senders in transactions before obtaining lock (pool.signer is immutable) + for _, tx := range news { + types.Sender(pool.signer, tx) + } + // Process all the new transaction and merge any errors into the original slice + pool.mu.Lock() + newErrs, dirtyAddrs := pool.addTxsLocked(news, local) + pool.mu.Unlock() + + var nilSlot = 0 + for _, err := range newErrs { + for errs[nilSlot] != nil { + nilSlot++ } - pool.promoteExecutables(addrs) + errs[nilSlot] = err + } + // Reorg the pool internals if needed and return + done := pool.requestPromoteExecutables(dirtyAddrs) + if sync { + <-done } return errs } +// addTxsLocked attempts to queue a batch of transactions if they are valid. +// The transaction pool lock must be held. +func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, *accountSet) { + dirty := newAccountSet(pool.signer) + errs := make([]error, len(txs)) + for i, tx := range txs { + replaced, err := pool.add(tx, local) + errs[i] = err + if err == nil && !replaced { + dirty.addTx(tx) + } + } + validTxMeter.Mark(int64(len(dirty.accounts))) + return errs, dirty +} + // Status returns the status (unknown/pending/queued) of a batch of transactions // identified by their hashes. func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { - pool.mu.RLock() - defer pool.mu.RUnlock() - status := make([]TxStatus, len(hashes)) for i, hash := range hashes { - if tx := pool.all.Get(hash); tx != nil { - from, _ := types.Sender(pool.signer, tx) // already validated - if pool.pending[from] != nil && pool.pending[from].txs.items[tx.Nonce()] != nil { - status[i] = TxStatusPending - } else { - status[i] = TxStatusQueued - } + tx := pool.Get(hash) + if tx == nil { + continue } + from, _ := types.Sender(pool.signer, tx) // already validated + pool.mu.RLock() + if txList := pool.pending[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { + status[i] = TxStatusPending + } else if txList := pool.queue[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { + status[i] = TxStatusQueued + } + // implicit else: the tx may have been included into a block between + // checking pool.Get and obtaining the lock. In that case, TxStatusUnknown is correct + pool.mu.RUnlock() } return status } -// Get returns a transaction if it is contained in the pool -// and nil otherwise. +// Get returns a transaction if it is contained in the pool and nil otherwise. func (pool *TxPool) Get(hash common.Hash) *types.Transaction { return pool.all.Get(hash) } @@ -906,7 +864,10 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { // Remove it from the list of known transactions pool.all.Remove(hash) if outofbound { - pool.priced.Removed() + pool.priced.Removed(1) + } + if pool.locals.contains(addr) { + localGauge.Dec(1) } // Remove the transaction from the pending lists and reset the account nonce if pending := pool.pending[addr]; pending != nil { @@ -921,35 +882,283 @@ func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { pool.enqueueTx(tx.Hash(), tx) } // Update the account nonce if needed - if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { - pool.pendingState.SetNonce(addr, nonce) - } + pool.pendingNonces.setIfLower(addr, tx.Nonce()) + // Reduce the pending counter + pendingGauge.Dec(int64(1 + len(invalids))) return } } // Transaction is in the future queue if future := pool.queue[addr]; future != nil { - future.Remove(tx) + if removed, _ := future.Remove(tx); removed { + // Reduce the queued counter + queuedGauge.Dec(1) + } if future.Empty() { delete(pool.queue, addr) } } } +// requestPromoteExecutables requests a pool reset to the new head block. +// The returned channel is closed when the reset has occurred. +func (pool *TxPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} { + select { + case pool.reqResetCh <- &txpoolResetRequest{oldHead, newHead}: + return <-pool.reorgDoneCh + case <-pool.reorgShutdownCh: + return pool.reorgShutdownCh + } +} + +// requestPromoteExecutables requests transaction promotion checks for the given addresses. +// The returned channel is closed when the promotion checks have occurred. +func (pool *TxPool) requestPromoteExecutables(set *accountSet) chan struct{} { + select { + case pool.reqPromoteCh <- set: + return <-pool.reorgDoneCh + case <-pool.reorgShutdownCh: + return pool.reorgShutdownCh + } +} + +// queueTxEvent enqueues a transaction event to be sent in the next reorg run. +func (pool *TxPool) queueTxEvent(tx *types.Transaction) { + select { + case pool.queueTxEventCh <- tx: + case <-pool.reorgShutdownCh: + } +} + +// scheduleReorgLoop schedules runs of reset and promoteExecutables. Code above should not +// call those methods directly, but request them being run using requestReset and +// requestPromoteExecutables instead. +func (pool *TxPool) scheduleReorgLoop() { + defer pool.wg.Done() + + var ( + curDone chan struct{} // non-nil while runReorg is active + nextDone = make(chan struct{}) + launchNextRun bool + reset *txpoolResetRequest + dirtyAccounts *accountSet + queuedEvents = make(map[common.Address]*txSortedMap) + ) + for { + // Launch next background reorg if needed + if curDone == nil && launchNextRun { + // Run the background reorg and announcements + go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents) + + // Prepare everything for the next round of reorg + curDone, nextDone = nextDone, make(chan struct{}) + launchNextRun = false + + reset, dirtyAccounts = nil, nil + queuedEvents = make(map[common.Address]*txSortedMap) + } + + select { + case req := <-pool.reqResetCh: + // Reset request: update head if request is already pending. + if reset == nil { + reset = req + } else { + reset.newHead = req.newHead + } + launchNextRun = true + pool.reorgDoneCh <- nextDone + + case req := <-pool.reqPromoteCh: + // Promote request: update address set if request is already pending. + if dirtyAccounts == nil { + dirtyAccounts = req + } else { + dirtyAccounts.merge(req) + } + launchNextRun = true + pool.reorgDoneCh <- nextDone + + case tx := <-pool.queueTxEventCh: + // Queue up the event, but don't schedule a reorg. It's up to the caller to + // request one later if they want the events sent. + addr, _ := types.Sender(pool.signer, tx) + if _, ok := queuedEvents[addr]; !ok { + queuedEvents[addr] = newTxSortedMap() + } + queuedEvents[addr].Put(tx) + + case <-curDone: + curDone = nil + + case <-pool.reorgShutdownCh: + // Wait for current run to finish. + if curDone != nil { + <-curDone + } + close(nextDone) + return + } + } +} + +// runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop. +func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*txSortedMap) { + defer close(done) + + var promoteAddrs []common.Address + if dirtyAccounts != nil { + promoteAddrs = dirtyAccounts.flatten() + } + pool.mu.Lock() + if reset != nil { + // Reset from the old head to the new, rescheduling any reorged transactions + pool.reset(reset.oldHead, reset.newHead) + + // Nonces were reset, discard any events that became stale + for addr := range events { + events[addr].Forward(pool.pendingNonces.get(addr)) + if events[addr].Len() == 0 { + delete(events, addr) + } + } + // Reset needs promote for all addresses + promoteAddrs = promoteAddrs[:0] + for addr := range pool.queue { + promoteAddrs = append(promoteAddrs, addr) + } + } + // Check for pending transactions for every account that sent new ones + promoted := pool.promoteExecutables(promoteAddrs) + for _, tx := range promoted { + addr, _ := types.Sender(pool.signer, tx) + if _, ok := events[addr]; !ok { + events[addr] = newTxSortedMap() + } + events[addr].Put(tx) + } + // If a new block appeared, validate the pool of pending transactions. This will + // remove any transaction that has been included in the block or was invalidated + // because of another transaction (e.g. higher gas price). + if reset != nil { + pool.demoteUnexecutables() + } + // Ensure pool.queue and pool.pending sizes stay within the configured limits. + pool.truncatePending() + pool.truncateQueue() + + // Update all accounts to the latest known pending nonce + for addr, list := range pool.pending { + txs := list.Flatten() // Heavy but will be cached and is needed by the miner anyway + pool.pendingNonces.set(addr, txs[len(txs)-1].Nonce()+1) + } + pool.mu.Unlock() + + // Notify subsystems for newly added transactions + if len(events) > 0 { + var txs []*types.Transaction + for _, set := range events { + txs = append(txs, set.Flatten()...) + } + pool.txFeed.Send(NewTxsEvent{txs}) + } +} + +// reset retrieves the current state of the blockchain and ensures the content +// of the transaction pool is valid with regard to the chain state. +func (pool *TxPool) reset(oldHead, newHead *types.Header) { + // If we're reorging an old state, reinject all dropped transactions + var reinject types.Transactions + + if oldHead != nil && oldHead.Hash() != newHead.ParentHash { + // If the reorg is too deep, avoid doing it (will happen during fast sync) + oldNum := oldHead.Number.Uint64() + newNum := newHead.Number.Uint64() + + if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { + log.Debug("Skipping deep transaction reorg", "depth", depth) + } else { + // Reorg seems shallow enough to pull in all transactions into memory + var discarded, included types.Transactions + var ( + rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) + add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) + ) + if rem == nil { + // This can happen if a setHead is performed, where we simply discard the old + // head from the chain. + // If that is the case, we don't have the lost transactions any more, and + // there's nothing to add + if newNum < oldNum { + // If the reorg ended up on a lower number, it's indicative of setHead being the cause + log.Debug("Skipping transaction reset caused by setHead", + "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) + } else { + // If we reorged to a same or higher number, then it's not a case of setHead + log.Warn("Transaction pool reset with missing oldhead", + "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) + } + return + } + for rem.NumberU64() > add.NumberU64() { + discarded = append(discarded, rem.Transactions()...) + if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { + log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) + return + } + } + for add.NumberU64() > rem.NumberU64() { + included = append(included, add.Transactions()...) + if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { + log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) + return + } + } + for rem.Hash() != add.Hash() { + discarded = append(discarded, rem.Transactions()...) + if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { + log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) + return + } + included = append(included, add.Transactions()...) + if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { + log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) + return + } + } + reinject = types.TxDifference(discarded, included) + } + } + // Initialize the internal state to the current head + if newHead == nil { + newHead = pool.chain.CurrentBlock().Header() // Special case during testing + } + statedb, err := pool.chain.StateAt(newHead.Root) + if err != nil { + log.Error("Failed to reset txpool state", "err", err) + return + } + pool.currentState = statedb + pool.pendingNonces = newTxNoncer(statedb) + pool.currentMaxGas = newHead.GasLimit + + // Inject any transactions discarded due to reorgs + log.Debug("Reinjecting stale transactions", "count", len(reinject)) + senderCacher.recover(pool.signer, reinject) + pool.addTxsLocked(reinject, false) + + // Update all fork indicator by next pending block number. + next := new(big.Int).Add(newHead.Number, big.NewInt(1)) + pool.istanbul = pool.chainconfig.IsIstanbul(next) +} + // promoteExecutables moves transactions that have become processable from the // future queue to the set of pending transactions. During this process, all // invalidated transactions (low nonce, low balance) are deleted. -func (pool *TxPool) promoteExecutables(accounts []common.Address) { +func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Transaction { // Track the promoted transactions to broadcast them at once var promoted []*types.Transaction - // Gather all the accounts potentially needing updates - if accounts == nil { - accounts = make([]common.Address, 0, len(pool.queue)) - for addr := range pool.queue { - accounts = append(accounts, addr) - } - } // Iterate over all accounts and promote any executable transactions for _, addr := range accounts { list := pool.queue[addr] @@ -957,157 +1166,185 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) { continue // Just in case someone calls with a non existing account } // Drop all transactions that are deemed too old (low nonce) - for _, tx := range list.Forward(pool.currentState.GetNonce(addr)) { + forwards := list.Forward(pool.currentState.GetNonce(addr)) + for _, tx := range forwards { hash := tx.Hash() - log.Trace("Removed old queued transaction", "hash", hash) pool.all.Remove(hash) - pool.priced.Removed() + log.Trace("Removed old queued transaction", "hash", hash) } // Drop all transactions that are too costly (low balance or out of gas) drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) for _, tx := range drops { hash := tx.Hash() - log.Trace("Removed unpayable queued transaction", "hash", hash) pool.all.Remove(hash) - pool.priced.Removed() - queuedNofundsCounter.Inc(1) + log.Trace("Removed unpayable queued transaction", "hash", hash) } + queuedNofundsMeter.Mark(int64(len(drops))) + // Gather all executable transactions and promote them - for _, tx := range list.Ready(pool.pendingState.GetNonce(addr)) { + readies := list.Ready(pool.pendingNonces.get(addr)) + for _, tx := range readies { hash := tx.Hash() if pool.promoteTx(addr, hash, tx) { log.Trace("Promoting queued transaction", "hash", hash) promoted = append(promoted, tx) } } + queuedGauge.Dec(int64(len(readies))) + // Drop all transactions over the allowed limit + var caps types.Transactions if !pool.locals.contains(addr) { - for _, tx := range list.Cap(int(pool.config.AccountQueue)) { + caps = list.Cap(int(pool.config.AccountQueue)) + for _, tx := range caps { hash := tx.Hash() pool.all.Remove(hash) - pool.priced.Removed() - queuedRateLimitCounter.Inc(1) log.Trace("Removed cap-exceeding queued transaction", "hash", hash) } + queuedRateLimitMeter.Mark(int64(len(caps))) + } + // Mark all the items dropped as removed + pool.priced.Removed(len(forwards) + len(drops) + len(caps)) + queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) + if pool.locals.contains(addr) { + localGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) } // Delete the entire queue entry if it became empty. if list.Empty() { delete(pool.queue, addr) } } - // Notify subsystem for new promoted transactions. - if len(promoted) > 0 { - go pool.txFeed.Send(NewTxsEvent{promoted}) - } - // If the pending limit is overflown, start equalizing allowances + return promoted +} + +// truncatePending removes transactions from the pending queue if the pool is above the +// pending limit. The algorithm tries to reduce transaction counts by an approximately +// equal number for all for accounts with many pending transactions. +func (pool *TxPool) truncatePending() { pending := uint64(0) for _, list := range pool.pending { pending += uint64(list.Len()) } - if pending > pool.config.GlobalSlots { - pendingBeforeCap := pending - // Assemble a spam order to penalize large transactors first - spammers := prque.New(nil) - for addr, list := range pool.pending { - // Only evict transactions from high rollers - if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { - spammers.Push(addr, int64(list.Len())) - } + if pending <= pool.config.GlobalSlots { + return + } + + pendingBeforeCap := pending + // Assemble a spam order to penalize large transactors first + spammers := prque.New(nil) + for addr, list := range pool.pending { + // Only evict transactions from high rollers + if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { + spammers.Push(addr, int64(list.Len())) } - // Gradually drop transactions from offenders - offenders := []common.Address{} - for pending > pool.config.GlobalSlots && !spammers.Empty() { - // Retrieve the next offender if not local address - offender, _ := spammers.Pop() - offenders = append(offenders, offender.(common.Address)) + } + // Gradually drop transactions from offenders + offenders := []common.Address{} + for pending > pool.config.GlobalSlots && !spammers.Empty() { + // Retrieve the next offender if not local address + offender, _ := spammers.Pop() + offenders = append(offenders, offender.(common.Address)) - // Equalize balances until all the same or below threshold - if len(offenders) > 1 { - // Calculate the equalization threshold for all current offenders - threshold := pool.pending[offender.(common.Address)].Len() + // Equalize balances until all the same or below threshold + if len(offenders) > 1 { + // Calculate the equalization threshold for all current offenders + threshold := pool.pending[offender.(common.Address)].Len() - // Iteratively reduce all offenders until below limit or threshold reached - for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { - for i := 0; i < len(offenders)-1; i++ { - list := pool.pending[offenders[i]] - for _, tx := range list.Cap(list.Len() - 1) { - // Drop the transaction from the global pools too - hash := tx.Hash() - pool.all.Remove(hash) - pool.priced.Removed() + // Iteratively reduce all offenders until below limit or threshold reached + for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { + for i := 0; i < len(offenders)-1; i++ { + list := pool.pending[offenders[i]] - // Update the account nonce to the dropped transaction - if nonce := tx.Nonce(); pool.pendingState.GetNonce(offenders[i]) > nonce { - pool.pendingState.SetNonce(offenders[i], nonce) - } - log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) - } - pending-- - } - } - } - } - // If still above threshold, reduce to limit or min allowance - if pending > pool.config.GlobalSlots && len(offenders) > 0 { - for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { - for _, addr := range offenders { - list := pool.pending[addr] - for _, tx := range list.Cap(list.Len() - 1) { + caps := list.Cap(list.Len() - 1) + for _, tx := range caps { // Drop the transaction from the global pools too hash := tx.Hash() pool.all.Remove(hash) - pool.priced.Removed() // Update the account nonce to the dropped transaction - if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { - pool.pendingState.SetNonce(addr, nonce) - } + pool.pendingNonces.setIfLower(offenders[i], tx.Nonce()) log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) } + pool.priced.Removed(len(caps)) + pendingGauge.Dec(int64(len(caps))) + if pool.locals.contains(offenders[i]) { + localGauge.Dec(int64(len(caps))) + } pending-- } } } - pendingRateLimitCounter.Inc(int64(pendingBeforeCap - pending)) } - // If we've queued more transactions than the hard limit, drop oldest ones + + // If still above threshold, reduce to limit or min allowance + if pending > pool.config.GlobalSlots && len(offenders) > 0 { + for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { + for _, addr := range offenders { + list := pool.pending[addr] + + caps := list.Cap(list.Len() - 1) + for _, tx := range caps { + // Drop the transaction from the global pools too + hash := tx.Hash() + pool.all.Remove(hash) + + // Update the account nonce to the dropped transaction + pool.pendingNonces.setIfLower(addr, tx.Nonce()) + log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) + } + pool.priced.Removed(len(caps)) + pendingGauge.Dec(int64(len(caps))) + if pool.locals.contains(addr) { + localGauge.Dec(int64(len(caps))) + } + pending-- + } + } + } + pendingRateLimitMeter.Mark(int64(pendingBeforeCap - pending)) +} + +// truncateQueue drops the oldes transactions in the queue if the pool is above the global queue limit. +func (pool *TxPool) truncateQueue() { queued := uint64(0) for _, list := range pool.queue { queued += uint64(list.Len()) } - if queued > pool.config.GlobalQueue { - // Sort all accounts with queued transactions by heartbeat - addresses := make(addressesByHeartbeat, 0, len(pool.queue)) - for addr := range pool.queue { - if !pool.locals.contains(addr) { // don't drop locals - addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) - } + if queued <= pool.config.GlobalQueue { + return + } + + // Sort all accounts with queued transactions by heartbeat + addresses := make(addressesByHeartbeat, 0, len(pool.queue)) + for addr := range pool.queue { + if !pool.locals.contains(addr) { // don't drop locals + addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) } - sort.Sort(addresses) + } + sort.Sort(addresses) - // Drop transactions until the total is below the limit or only locals remain - for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { - addr := addresses[len(addresses)-1] - list := pool.queue[addr.address] + // Drop transactions until the total is below the limit or only locals remain + for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { + addr := addresses[len(addresses)-1] + list := pool.queue[addr.address] - addresses = addresses[:len(addresses)-1] + addresses = addresses[:len(addresses)-1] - // Drop all transactions if they are less than the overflow - if size := uint64(list.Len()); size <= drop { - for _, tx := range list.Flatten() { - pool.removeTx(tx.Hash(), true) - } - drop -= size - queuedRateLimitCounter.Inc(int64(size)) - continue - } - // Otherwise drop only last few transactions - txs := list.Flatten() - for i := len(txs) - 1; i >= 0 && drop > 0; i-- { - pool.removeTx(txs[i].Hash(), true) - drop-- - queuedRateLimitCounter.Inc(1) + // Drop all transactions if they are less than the overflow + if size := uint64(list.Len()); size <= drop { + for _, tx := range list.Flatten() { + pool.removeTx(tx.Hash(), true) } + drop -= size + queuedRateLimitMeter.Mark(int64(size)) + continue + } + // Otherwise drop only last few transactions + txs := list.Flatten() + for i := len(txs) - 1; i >= 0 && drop > 0; i-- { + pool.removeTx(txs[i].Hash(), true) + drop-- + queuedRateLimitMeter.Mark(1) } } } @@ -1121,11 +1358,11 @@ func (pool *TxPool) demoteUnexecutables() { nonce := pool.currentState.GetNonce(addr) // Drop all transactions that are deemed too old (low nonce) - for _, tx := range list.Forward(nonce) { + olds := list.Forward(nonce) + for _, tx := range olds { hash := tx.Hash() - log.Trace("Removed old pending transaction", "hash", hash) pool.all.Remove(hash) - pool.priced.Removed() + log.Trace("Removed old pending transaction", "hash", hash) } // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) @@ -1133,21 +1370,28 @@ func (pool *TxPool) demoteUnexecutables() { hash := tx.Hash() log.Trace("Removed unpayable pending transaction", "hash", hash) pool.all.Remove(hash) - pool.priced.Removed() - pendingNofundsCounter.Inc(1) } + pool.priced.Removed(len(olds) + len(drops)) + pendingNofundsMeter.Mark(int64(len(drops))) + for _, tx := range invalids { hash := tx.Hash() log.Trace("Demoting pending transaction", "hash", hash) pool.enqueueTx(hash, tx) } + pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) + if pool.locals.contains(addr) { + localGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) + } // If there's a gap in front, alert (should never happen) and postpone all transactions if list.Len() > 0 && list.txs.Get(nonce) == nil { - for _, tx := range list.Cap(0) { + gapped := list.Cap(0) + for _, tx := range gapped { hash := tx.Hash() log.Error("Demoting invalidated transaction", "hash", hash) pool.enqueueTx(hash, tx) } + pendingGauge.Dec(int64(len(gapped))) } // Delete the entire queue entry if it became empty. if list.Empty() { @@ -1179,11 +1423,15 @@ type accountSet struct { // newAccountSet creates a new address set with an associated signer for sender // derivations. -func newAccountSet(signer types.Signer) *accountSet { - return &accountSet{ +func newAccountSet(signer types.Signer, addrs ...common.Address) *accountSet { + as := &accountSet{ accounts: make(map[common.Address]struct{}), signer: signer, } + for _, addr := range addrs { + as.add(addr) + } + return as } // contains checks if a given address is contained within the set. @@ -1207,6 +1455,13 @@ func (as *accountSet) add(addr common.Address) { as.cache = nil } +// addTx adds the sender of tx into the set. +func (as *accountSet) addTx(tx *types.Transaction) { + if addr, err := types.Sender(as.signer, tx); err == nil { + as.add(addr) + } +} + // flatten returns the list of addresses within this set, also caching it for later // reuse. The returned slice should not be changed! func (as *accountSet) flatten() []common.Address { @@ -1220,6 +1475,14 @@ func (as *accountSet) flatten() []common.Address { return *as.cache } +// merge adds all addresses from the 'other' set into 'as'. +func (as *accountSet) merge(other *accountSet) { + for addr := range other.accounts { + as.accounts[addr] = struct{}{} + } + as.cache = nil +} + // txLookup is used internally by TxPool to track transactions while allowing lookup without // mutex contention. // diff --git a/vendor/github.com/ethereum/go-ethereum/core/types.go b/vendor/github.com/ethereum/go-ethereum/core/types.go index d0bbaf0aa..4c5b74a49 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types.go @@ -25,22 +25,27 @@ import ( // Validator is an interface which defines the standard for block validation. It // is only responsible for validating block contents, as the header validation is // done by the specific consensus engines. -// type Validator interface { // ValidateBody validates the given block's content. ValidateBody(block *types.Block) error // ValidateState validates the given statedb and optionally the receipts and // gas used. - ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error + ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error +} + +// Prefetcher is an interface for pre-caching transaction signatures and state. +type Prefetcher interface { + // Prefetch processes the state changes according to the Ethereum rules by running + // the transaction messages using the statedb, but any changes are discarded. The + // only goal is to pre-cache transaction signatures and state trie nodes. + Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) } // Processor is an interface for processing blocks using a given initial state. -// -// Process takes the block to be processed and the statedb upon which the -// initial state is based. It should return the receipts generated, amount -// of gas used in the process and return an error if any of the internal rules -// failed. type Processor interface { + // Process processes the state changes according to the Ethereum rules by running + // the transaction messages using the statedb and applying any rewards to both + // the processor (coinbase) and any included uncles. Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/block.go b/vendor/github.com/ethereum/go-ethereum/core/types/block.go index 867d77db3..b0ec7fc77 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/block.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/block.go @@ -19,12 +19,13 @@ package types import ( "encoding/binary" + "fmt" "io" "math/big" + "reflect" "sort" "sync/atomic" "time" - "unsafe" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -34,7 +35,7 @@ import ( var ( EmptyRootHash = DeriveSha(Transactions{}) - EmptyUncleHash = CalcUncleHash(nil) + EmptyUncleHash = rlpHash([]*Header(nil)) ) // A BlockNonce is a 64-bit hash which proves (combined with the @@ -102,10 +103,31 @@ func (h *Header) Hash() common.Hash { return rlpHash(h) } +var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) + // Size returns the approximate memory used by all internal contents. It is used // to approximate and limit the memory consumption of various caches. func (h *Header) Size() common.StorageSize { - return common.StorageSize(unsafe.Sizeof(*h)) + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen())/8) + return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen())/8) +} + +// SanityCheck checks a few basic things -- these checks are way beyond what +// any 'sane' production values should hold, and can mainly be used to prevent +// that the unbounded fields are stuffed with junk data to add processing +// overhead +func (h *Header) SanityCheck() error { + if h.Number != nil && !h.Number.IsUint64() { + return fmt.Errorf("too large block number: bitlen %d", h.Number.BitLen()) + } + if h.Difficulty != nil { + if diffLen := h.Difficulty.BitLen(); diffLen > 80 { + return fmt.Errorf("too large block difficulty: bitlen %d", diffLen) + } + } + if eLen := len(h.Extra); eLen > 100*1024 { + return fmt.Errorf("too large block extradata: size %d", eLen) + } + return nil } func rlpHash(x interface{}) (h common.Hash) { @@ -314,6 +336,12 @@ func (b *Block) Size() common.StorageSize { return common.StorageSize(c) } +// SanityCheck can be used to prevent that unbounded fields are +// stuffed with junk data to add processing overhead +func (b *Block) SanityCheck() error { + return b.header.SanityCheck() +} + type writeCounter common.StorageSize func (c *writeCounter) Write(b []byte) (int, error) { @@ -322,6 +350,9 @@ func (c *writeCounter) Write(b []byte) (int, error) { } func CalcUncleHash(uncles []*Header) common.Hash { + if len(uncles) == 0 { + return EmptyUncleHash + } return rlpHash(uncles) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go index 1b5ae3c65..6e9433947 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_log_json.go @@ -12,6 +12,7 @@ import ( var _ = (*logMarshaling)(nil) +// MarshalJSON marshals as JSON. func (l Log) MarshalJSON() ([]byte, error) { type Log struct { Address common.Address `json:"address" gencodec:"required"` @@ -37,6 +38,7 @@ func (l Log) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (l *Log) UnmarshalJSON(input []byte) error { type Log struct { Address *common.Address `json:"address" gencodec:"required"` diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go index 5c807a4cc..790ed65b5 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_receipt_json.go @@ -5,6 +5,7 @@ package types import ( "encoding/json" "errors" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -23,6 +24,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex hexutil.Uint `json:"transactionIndex"` } var enc Receipt enc.PostState = r.PostState @@ -33,6 +37,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) { enc.TxHash = r.TxHash enc.ContractAddress = r.ContractAddress enc.GasUsed = hexutil.Uint64(r.GasUsed) + enc.BlockHash = r.BlockHash + enc.BlockNumber = (*hexutil.Big)(r.BlockNumber) + enc.TransactionIndex = hexutil.Uint(r.TransactionIndex) return json.Marshal(&enc) } @@ -47,6 +54,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { TxHash *common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress *common.Address `json:"contractAddress"` GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` + TransactionIndex *hexutil.Uint `json:"transactionIndex"` } var dec Receipt if err := json.Unmarshal(input, &dec); err != nil { @@ -81,5 +91,14 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'gasUsed' for Receipt") } r.GasUsed = uint64(*dec.GasUsed) + if dec.BlockHash != nil { + r.BlockHash = *dec.BlockHash + } + if dec.BlockNumber != nil { + r.BlockNumber = (*big.Int)(dec.BlockNumber) + } + if dec.TransactionIndex != nil { + r.TransactionIndex = uint(*dec.TransactionIndex) + } return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go b/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go index c27da6709..e676058ec 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/gen_tx_json.go @@ -13,6 +13,7 @@ import ( var _ = (*txdataMarshaling)(nil) +// MarshalJSON marshals as JSON. func (t txdata) MarshalJSON() ([]byte, error) { type txdata struct { AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"` @@ -40,6 +41,7 @@ func (t txdata) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (t *txdata) UnmarshalJSON(input []byte) error { type txdata struct { AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/log.go b/vendor/github.com/ethereum/go-ethereum/core/types/log.go index 717cd2e5a..006f62bbf 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/log.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/log.go @@ -68,7 +68,11 @@ type rlpLog struct { Data []byte } -type rlpStorageLog struct { +// rlpStorageLog is the storage encoding of a log. +type rlpStorageLog rlpLog + +// legacyRlpStorageLog is the previous storage encoding of a log including some redundant fields. +type legacyRlpStorageLog struct { Address common.Address Topics []common.Hash Data []byte @@ -101,31 +105,38 @@ type LogForStorage Log // EncodeRLP implements rlp.Encoder. func (l *LogForStorage) EncodeRLP(w io.Writer) error { return rlp.Encode(w, rlpStorageLog{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: l.BlockNumber, - TxHash: l.TxHash, - TxIndex: l.TxIndex, - BlockHash: l.BlockHash, - Index: l.Index, + Address: l.Address, + Topics: l.Topics, + Data: l.Data, }) } // DecodeRLP implements rlp.Decoder. +// +// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later. func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error { + blob, err := s.Raw() + if err != nil { + return err + } var dec rlpStorageLog - err := s.Decode(&dec) + err = rlp.DecodeBytes(blob, &dec) if err == nil { *l = LogForStorage{ - Address: dec.Address, - Topics: dec.Topics, - Data: dec.Data, - BlockNumber: dec.BlockNumber, - TxHash: dec.TxHash, - TxIndex: dec.TxIndex, - BlockHash: dec.BlockHash, - Index: dec.Index, + Address: dec.Address, + Topics: dec.Topics, + Data: dec.Data, + } + } else { + // Try to decode log with previous definition. + var dec legacyRlpStorageLog + err = rlp.DecodeBytes(blob, &dec) + if err == nil { + *l = LogForStorage{ + Address: dec.Address, + Topics: dec.Topics, + Data: dec.Data, + } } } return err diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go b/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go index 3d1fc95aa..a96c7525e 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/receipt.go @@ -18,12 +18,16 @@ package types import ( "bytes" + "errors" "fmt" "io" + "math/big" "unsafe" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -44,17 +48,24 @@ const ( // Receipt represents the results of a transaction. type Receipt struct { - // Consensus fields + // Consensus fields: These fields are defined by the Yellow Paper PostState []byte `json:"root"` Status uint64 `json:"status"` CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"` - // Implementation fields (don't reorder!) + // Implementation fields: These fields are added by geth when processing a transaction. + // They are stored in the chain database. TxHash common.Hash `json:"transactionHash" gencodec:"required"` ContractAddress common.Address `json:"contractAddress"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` + + // Inclusion information: These fields provide information about the inclusion of the + // transaction corresponding to this receipt. + BlockHash common.Hash `json:"blockHash,omitempty"` + BlockNumber *big.Int `json:"blockNumber,omitempty"` + TransactionIndex uint `json:"transactionIndex"` } type receiptMarshaling struct { @@ -62,6 +73,8 @@ type receiptMarshaling struct { Status hexutil.Uint64 CumulativeGasUsed hexutil.Uint64 GasUsed hexutil.Uint64 + BlockNumber *hexutil.Big + TransactionIndex hexutil.Uint } // receiptRLP is the consensus encoding of a receipt. @@ -72,7 +85,25 @@ type receiptRLP struct { Logs []*Log } -type receiptStorageRLP struct { +// storedReceiptRLP is the storage encoding of a receipt. +type storedReceiptRLP struct { + PostStateOrStatus []byte + CumulativeGasUsed uint64 + Logs []*LogForStorage +} + +// v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4. +type v4StoredReceiptRLP struct { + PostStateOrStatus []byte + CumulativeGasUsed uint64 + TxHash common.Hash + ContractAddress common.Address + Logs []*LogForStorage + GasUsed uint64 +} + +// v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields. +type v3StoredReceiptRLP struct { PostStateOrStatus []byte CumulativeGasUsed uint64 Bloom Bloom @@ -156,14 +187,10 @@ type ReceiptForStorage Receipt // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt // into an RLP stream. func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { - enc := &receiptStorageRLP{ + enc := &storedReceiptRLP{ PostStateOrStatus: (*Receipt)(r).statusEncoding(), CumulativeGasUsed: r.CumulativeGasUsed, - Bloom: r.Bloom, - TxHash: r.TxHash, - ContractAddress: r.ContractAddress, Logs: make([]*LogForStorage, len(r.Logs)), - GasUsed: r.GasUsed, } for i, log := range r.Logs { enc.Logs[i] = (*LogForStorage)(log) @@ -174,21 +201,79 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation // fields of a receipt from an RLP stream. func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { - var dec receiptStorageRLP - if err := s.Decode(&dec); err != nil { + // Retrieve the entire receipt blob as we need to try multiple decoders + blob, err := s.Raw() + if err != nil { return err } - if err := (*Receipt)(r).setStatus(dec.PostStateOrStatus); err != nil { + // Try decoding from the newest format for future proofness, then the older one + // for old nodes that just upgraded. V4 was an intermediate unreleased format so + // we do need to decode it, but it's not common (try last). + if err := decodeStoredReceiptRLP(r, blob); err == nil { + return nil + } + if err := decodeV3StoredReceiptRLP(r, blob); err == nil { + return nil + } + return decodeV4StoredReceiptRLP(r, blob) +} + +func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { + var stored storedReceiptRLP + if err := rlp.DecodeBytes(blob, &stored); err != nil { return err } - // Assign the consensus fields - r.CumulativeGasUsed, r.Bloom = dec.CumulativeGasUsed, dec.Bloom - r.Logs = make([]*Log, len(dec.Logs)) - for i, log := range dec.Logs { + if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { + return err + } + r.CumulativeGasUsed = stored.CumulativeGasUsed + r.Logs = make([]*Log, len(stored.Logs)) + for i, log := range stored.Logs { + r.Logs[i] = (*Log)(log) + } + r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) + + return nil +} + +func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { + var stored v4StoredReceiptRLP + if err := rlp.DecodeBytes(blob, &stored); err != nil { + return err + } + if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { + return err + } + r.CumulativeGasUsed = stored.CumulativeGasUsed + r.TxHash = stored.TxHash + r.ContractAddress = stored.ContractAddress + r.GasUsed = stored.GasUsed + r.Logs = make([]*Log, len(stored.Logs)) + for i, log := range stored.Logs { + r.Logs[i] = (*Log)(log) + } + r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) + + return nil +} + +func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { + var stored v3StoredReceiptRLP + if err := rlp.DecodeBytes(blob, &stored); err != nil { + return err + } + if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { + return err + } + r.CumulativeGasUsed = stored.CumulativeGasUsed + r.Bloom = stored.Bloom + r.TxHash = stored.TxHash + r.ContractAddress = stored.ContractAddress + r.GasUsed = stored.GasUsed + r.Logs = make([]*Log, len(stored.Logs)) + for i, log := range stored.Logs { r.Logs[i] = (*Log)(log) } - // Assign the implementation fields - r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed return nil } @@ -206,3 +291,46 @@ func (r Receipts) GetRlp(i int) []byte { } return bytes } + +// DeriveFields fills the receipts with their computed fields based on consensus +// data and contextual infos like containing block and transactions. +func (r Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, txs Transactions) error { + signer := MakeSigner(config, new(big.Int).SetUint64(number)) + + logIndex := uint(0) + if len(txs) != len(r) { + return errors.New("transaction and receipt count mismatch") + } + for i := 0; i < len(r); i++ { + // The transaction hash can be retrieved from the transaction itself + r[i].TxHash = txs[i].Hash() + + // block location fields + r[i].BlockHash = hash + r[i].BlockNumber = new(big.Int).SetUint64(number) + r[i].TransactionIndex = uint(i) + + // The contract address can be derived from the transaction itself + if txs[i].To() == nil { + // Deriving the signer is expensive, only do if it's actually needed + from, _ := Sender(signer, txs[i]) + r[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) + } + // The used gas can be calculated based on previous r + if i == 0 { + r[i].GasUsed = r[i].CumulativeGasUsed + } else { + r[i].GasUsed = r[i].CumulativeGasUsed - r[i-1].CumulativeGasUsed + } + // The derived log fields can simply be set from the block and transaction + for j := 0; j < len(r[i].Logs); j++ { + r[i].Logs[j].BlockNumber = number + r[i].Logs[j].BlockHash = hash + r[i].Logs[j].TxHash = r[i].TxHash + r[i].Logs[j].TxIndex = uint(i) + r[i].Logs[j].Index = logIndex + logIndex++ + } + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go b/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go index ba3d5de91..3eb8df0ac 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/transaction.go @@ -252,7 +252,9 @@ func (tx *Transaction) Cost() *big.Int { return total } -func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) { +// RawSignatureValues returns the V, R, S signature values of the transaction. +// The return values should not be modified by the caller. +func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) { return tx.data.V, tx.data.R, tx.data.S } diff --git a/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go b/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go index 63132048e..842fedbd0 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go +++ b/vendor/github.com/ethereum/go-ethereum/core/types/transaction_signing.go @@ -193,8 +193,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool { // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - if len(sig) != 65 { - panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig))) + if len(sig) != crypto.SignatureLength { + panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)) } r = new(big.Int).SetBytes(sig[:32]) s = new(big.Int).SetBytes(sig[32:64]) @@ -229,7 +229,7 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo } // encode the signature in uncompressed format r, s := R.Bytes(), S.Bytes() - sig := make([]byte, 65) + sig := make([]byte, crypto.SignatureLength) copy(sig[32-len(r):32], r) copy(sig[64-len(s):64], s) sig[64] = V diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/common.go b/vendor/github.com/ethereum/go-ethereum/core/vm/common.go index 17de38dec..d592a9410 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/common.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/common.go @@ -23,13 +23,31 @@ import ( "github.com/ethereum/go-ethereum/common/math" ) -// calculates the memory size required for a step -func calcMemSize(off, l *big.Int) *big.Int { - if l.Sign() == 0 { - return common.Big0 +// calcMemSize64 calculates the required memory size, and returns +// the size and whether the result overflowed uint64 +func calcMemSize64(off, l *big.Int) (uint64, bool) { + if !l.IsUint64() { + return 0, true } + return calcMemSize64WithUint(off, l.Uint64()) +} - return new(big.Int).Add(off, l) +// calcMemSize64WithUint calculates the required memory size, and returns +// the size and whether the result overflowed uint64 +// Identical to calcMemSize64, but length is a uint64 +func calcMemSize64WithUint(off *big.Int, length64 uint64) (uint64, bool) { + // if length is zero, memsize is always zero, regardless of offset + if length64 == 0 { + return 0, false + } + // Check that offset doesn't overflow + if !off.IsUint64() { + return 0, true + } + offset64 := off.Uint64() + val := offset64 + length64 + // if value < either of it's parts, then it overflowed + return val, val < offset64 } // getData returns a slice from the data based on the start and size and pads @@ -59,7 +77,7 @@ func getDataBig(data []byte, start *big.Int, size *big.Int) []byte { // bigUint64 returns the integer casted to a uint64 and returns whether it // overflowed in the process. func bigUint64(v *big.Int) (uint64, bool) { - return v.Uint64(), v.BitLen() > 64 + return v.Uint64(), !v.IsUint64() } // toWordSize returns the ceiled word size required for memory expansion. diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go b/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go index 20baa6e75..375e24bc1 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/contract.go @@ -162,7 +162,7 @@ func (c *Contract) Address() common.Address { return c.self.Address() } -// Value returns the contracts value (sent to it from it's caller) +// Value returns the contract's value (sent to it from it's caller) func (c *Contract) Value() *big.Int { return c.value } diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go b/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go index 20b741f8f..875054f89 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/contracts.go @@ -18,12 +18,14 @@ package vm import ( "crypto/sha256" + "encoding/binary" "errors" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/blake2b" "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/params" "golang.org/x/crypto/ripemd160" @@ -54,9 +56,23 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{5}): &bigModExp{}, - common.BytesToAddress([]byte{6}): &bn256Add{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, - common.BytesToAddress([]byte{8}): &bn256Pairing{}, + common.BytesToAddress([]byte{6}): &bn256AddByzantium{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{}, + common.BytesToAddress([]byte{8}): &bn256PairingByzantium{}, +} + +// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum +// contracts used in the Istanbul release. +var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, } // RunPrecompiledContract runs and evaluates the output of a precompiled contract. @@ -271,15 +287,9 @@ func newTwistPoint(blob []byte) (*bn256.G2, error) { return p, nil } -// bn256Add implements a native elliptic curve point addition. -type bn256Add struct{} - -// RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256Add) RequiredGas(input []byte) uint64 { - return params.Bn256AddGas -} - -func (c *bn256Add) Run(input []byte) ([]byte, error) { +// runBn256Add implements the Bn256Add precompile, referenced by both +// Byzantium and Istanbul operations. +func runBn256Add(input []byte) ([]byte, error) { x, err := newCurvePoint(getData(input, 0, 64)) if err != nil { return nil, err @@ -293,15 +303,35 @@ func (c *bn256Add) Run(input []byte) ([]byte, error) { return res.Marshal(), nil } -// bn256ScalarMul implements a native elliptic curve scalar multiplication. -type bn256ScalarMul struct{} +// bn256Add implements a native elliptic curve point addition conforming to +// Istanbul consensus rules. +type bn256AddIstanbul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { - return params.Bn256ScalarMulGas +func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasIstanbul } -func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) { +func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) { + return runBn256Add(input) +} + +// bn256AddByzantium implements a native elliptic curve point addition +// conforming to Byzantium consensus rules. +type bn256AddByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasByzantium +} + +func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) { + return runBn256Add(input) +} + +// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by +// both Byzantium and Istanbul operations. +func runBn256ScalarMul(input []byte) ([]byte, error) { p, err := newCurvePoint(getData(input, 0, 64)) if err != nil { return nil, err @@ -311,6 +341,32 @@ func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) { return res.Marshal(), nil } +// bn256ScalarMulIstanbul implements a native elliptic curve scalar +// multiplication conforming to Istanbul consensus rules. +type bn256ScalarMulIstanbul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256ScalarMulGasIstanbul +} + +func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) { + return runBn256ScalarMul(input) +} + +// bn256ScalarMulByzantium implements a native elliptic curve scalar +// multiplication conforming to Byzantium consensus rules. +type bn256ScalarMulByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256ScalarMulGasByzantium +} + +func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) { + return runBn256ScalarMul(input) +} + var ( // true32Byte is returned if the bn256 pairing check succeeds. true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} @@ -322,15 +378,9 @@ var ( errBadPairingInput = errors.New("bad elliptic curve pairing size") ) -// bn256Pairing implements a pairing pre-compile for the bn256 curve -type bn256Pairing struct{} - -// RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256Pairing) RequiredGas(input []byte) uint64 { - return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas -} - -func (c *bn256Pairing) Run(input []byte) ([]byte, error) { +// runBn256Pairing implements the Bn256Pairing precompile, referenced by both +// Byzantium and Istanbul operations. +func runBn256Pairing(input []byte) ([]byte, error) { // Handle some corner cases cheaply if len(input)%192 > 0 { return nil, errBadPairingInput @@ -358,3 +408,90 @@ func (c *bn256Pairing) Run(input []byte) ([]byte, error) { } return false32Byte, nil } + +// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve +// conforming to Istanbul consensus rules. +type bn256PairingIstanbul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul +} + +func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) { + return runBn256Pairing(input) +} + +// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve +// conforming to Byzantium consensus rules. +type bn256PairingByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium +} + +func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { + return runBn256Pairing(input) +} + +type blake2F struct{} + +func (c *blake2F) RequiredGas(input []byte) uint64 { + // If the input is malformed, we can't calculate the gas, return 0 and let the + // actual call choke and fault. + if len(input) != blake2FInputLength { + return 0 + } + return uint64(binary.BigEndian.Uint32(input[0:4])) +} + +const ( + blake2FInputLength = 213 + blake2FFinalBlockBytes = byte(1) + blake2FNonFinalBlockBytes = byte(0) +) + +var ( + errBlake2FInvalidInputLength = errors.New("invalid input length") + errBlake2FInvalidFinalFlag = errors.New("invalid final flag") +) + +func (c *blake2F) Run(input []byte) ([]byte, error) { + // Make sure the input is valid (correct lenth and final flag) + if len(input) != blake2FInputLength { + return nil, errBlake2FInvalidInputLength + } + if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { + return nil, errBlake2FInvalidFinalFlag + } + // Parse the input into the Blake2b call parameters + var ( + rounds = binary.BigEndian.Uint32(input[0:4]) + final = (input[212] == blake2FFinalBlockBytes) + + h [8]uint64 + m [16]uint64 + t [2]uint64 + ) + for i := 0; i < 8; i++ { + offset := 4 + i*8 + h[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + for i := 0; i < 16; i++ { + offset := 68 + i*8 + m[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + t[0] = binary.LittleEndian.Uint64(input[196:204]) + t[1] = binary.LittleEndian.Uint64(input[204:212]) + + // Execute the compression function, extract and return the result + blake2b.F(&h, m, t, final, rounds) + + output := make([]byte, 64) + for i := 0; i < 8; i++ { + offset := i * 8 + binary.LittleEndian.PutUint64(output[offset:offset+8], h[i]) + } + return output, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go b/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go new file mode 100644 index 000000000..075f5b760 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/eips.go @@ -0,0 +1,92 @@ +// Copyright 2019 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 vm + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/params" +) + +// EnableEIP enables the given EIP on the config. +// This operation writes in-place, and callers need to ensure that the globally +// defined jump tables are not polluted. +func EnableEIP(eipNum int, jt *JumpTable) error { + switch eipNum { + case 2200: + enable2200(jt) + case 1884: + enable1884(jt) + case 1344: + enable1344(jt) + default: + return fmt.Errorf("undefined eip %d", eipNum) + } + return nil +} + +// enable1884 applies EIP-1884 to the given jump table: +// - Increase cost of BALANCE to 700 +// - Increase cost of EXTCODEHASH to 700 +// - Increase cost of SLOAD to 800 +// - Define SELFBALANCE, with cost GasFastStep (5) +func enable1884(jt *JumpTable) { + // Gas cost changes + jt[BALANCE].constantGas = params.BalanceGasEIP1884 + jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884 + jt[SLOAD].constantGas = params.SloadGasEIP1884 + + // New opcode + jt[SELFBALANCE] = operation{ + execute: opSelfBalance, + constantGas: GasFastStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, + } +} + +func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + balance := interpreter.intPool.get().Set(interpreter.evm.StateDB.GetBalance(contract.Address())) + stack.push(balance) + return nil, nil +} + +// enable1344 applies EIP-1344 (ChainID Opcode) +// - Adds an opcode that returns the current chain’s EIP-155 unique identifier +func enable1344(jt *JumpTable) { + // New opcode + jt[CHAINID] = operation{ + execute: opChainID, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, + } +} + +// opChainID implements CHAINID opcode +func opChainID(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + chainId := interpreter.intPool.get().Set(interpreter.evm.chainConfig.ChainID) + stack.push(chainId) + return nil, nil +} + +// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE) +func enable2200(jt *JumpTable) { + jt[SSTORE].dynamicGas = gasSStoreEIP2200 +} diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/evm.go b/vendor/github.com/ethereum/go-ethereum/core/vm/evm.go index ba4d1e9eb..751c1fdc1 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/evm.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/evm.go @@ -35,7 +35,7 @@ type ( CanTransferFunc func(StateDB, common.Address, *big.Int) bool // TransferFunc is the signature of a transfer function TransferFunc func(StateDB, common.Address, common.Address, *big.Int) - // GetHashFunc returns the nth block hash in the blockchain + // GetHashFunc returns the n'th block hash in the blockchain // and is used by the BLOCKHASH EVM op code. GetHashFunc func(uint64) common.Hash ) @@ -44,9 +44,12 @@ type ( func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { if contract.CodeAddr != nil { precompiles := PrecompiledContractsHomestead - if evm.ChainConfig().IsByzantium(evm.BlockNumber) { + if evm.chainRules.IsByzantium { precompiles = PrecompiledContractsByzantium } + if evm.chainRules.IsIstanbul { + precompiles = PrecompiledContractsIstanbul + } if p := precompiles[*contract.CodeAddr]; p != nil { return RunPrecompiledContract(p, input, contract) } @@ -169,6 +172,11 @@ func (evm *EVM) Cancel() { atomic.StoreInt32(&evm.abort, 1) } +// Cancelled returns true if Cancel has been called +func (evm *EVM) Cancelled() bool { + return atomic.LoadInt32(&evm.abort) == 1 +} + // Interpreter returns the current interpreter func (evm *EVM) Interpreter() Interpreter { return evm.interpreter @@ -198,10 +206,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas ) if !evm.StateDB.Exist(addr) { precompiles := PrecompiledContractsHomestead - if evm.ChainConfig().IsByzantium(evm.BlockNumber) { + if evm.chainRules.IsByzantium { precompiles = PrecompiledContractsByzantium } - if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { + if evm.chainRules.IsIstanbul { + precompiles = PrecompiledContractsIstanbul + } + if precompiles[addr] == nil && evm.chainRules.IsEIP158 && value.Sign() == 0 { // Calling a non existing account, don't do anything, but ping the tracer if evm.vmConfig.Debug && evm.depth == 0 { evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) @@ -267,9 +278,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, snapshot = evm.StateDB.Snapshot() to = AccountRef(caller.Address()) ) - // initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. contract := NewContract(caller, to, value, gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) @@ -333,9 +343,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte to = AccountRef(addr) snapshot = evm.StateDB.Snapshot() ) - // Initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. contract := NewContract(caller, to, new(big.Int), gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) @@ -391,14 +400,13 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, // Create a new account on the state snapshot := evm.StateDB.Snapshot() evm.StateDB.CreateAccount(address) - if evm.ChainConfig().IsEIP158(evm.BlockNumber) { + if evm.chainRules.IsEIP158 { evm.StateDB.SetNonce(address, 1) } evm.Transfer(evm.StateDB, caller.Address(), address, value) - // initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. contract := NewContract(caller, AccountRef(address), value, gas) contract.SetCodeOptionalHash(&address, codeAndHash) @@ -414,7 +422,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, ret, err := run(evm, contract, nil, false) // check whether the max code size has been exceeded - maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize + maxCodeSizeExceeded := evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize // if the contract creation ran successfully and no errors were returned // calculate the gas required to store the code. If the code could not // be stored due to not enough gas set an error and let it be handled @@ -431,7 +439,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in homestead this also counts for code storage gas errors. - if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { + if maxCodeSizeExceeded || (err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas)) { evm.StateDB.RevertToSnapshot(snapshot) if err != errExecutionReverted { contract.UseGas(contract.Gas) diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/gas.go b/vendor/github.com/ethereum/go-ethereum/core/vm/gas.go index bba7058c7..bd8b4f104 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/gas.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/gas.go @@ -18,8 +18,6 @@ package vm import ( "math/big" - - "github.com/ethereum/go-ethereum/params" ) // Gas costs @@ -30,28 +28,24 @@ const ( GasMidStep uint64 = 8 GasSlowStep uint64 = 10 GasExtStep uint64 = 20 - - GasReturn uint64 = 0 - GasStop uint64 = 0 - GasContractByte uint64 = 200 ) // calcGas returns the actual gas cost of the call. // -// The cost of gas was changed during the homestead price change HF. To allow for EIP150 -// to be implemented. The returned gas is gas - base * 63 / 64. -func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) { - if gasTable.CreateBySuicide > 0 { +// The cost of gas was changed during the homestead price change HF. +// As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64. +func callGas(isEip150 bool, availableGas, base uint64, callCost *big.Int) (uint64, error) { + if isEip150 { availableGas = availableGas - base gas := availableGas - availableGas/64 // If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150 // is smaller than the requested amount. Therefor we return the new gas instead // of returning an error. - if callCost.BitLen() > 64 || gas < callCost.Uint64() { + if !callCost.IsUint64() || gas < callCost.Uint64() { return gas, nil } } - if callCost.BitLen() > 64 { + if !callCost.IsUint64() { return 0, errGasUintOverflow } diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go index 9203e10a7..1d3c4f100 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/gas_table.go @@ -17,29 +17,27 @@ package vm import ( + "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" ) -// memoryGasCosts calculates the quadratic gas for memory expansion. It does so +// memoryGasCost calculates the quadratic gas for memory expansion. It does so // only for the memory region that is expanded, not the total memory. func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { - if newMemSize == 0 { return 0, nil } - // The maximum that will fit in a uint64 is max_word_count - 1 - // anything above that will result in an overflow. - // Additionally, a newMemSize which results in a - // newMemSizeWords larger than 0x7ffffffff will cause the square operation - // to overflow. - // The constant 0xffffffffe0 is the highest number that can be used without - // overflowing the gas calculation - if newMemSize > 0xffffffffe0 { + // The maximum that will fit in a uint64 is max_word_count - 1. Anything above + // that will result in an overflow. Additionally, a newMemSize which results in + // a newMemSizeWords larger than 0xFFFFFFFF will cause the square operation to + // overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used + // without overflowing the gas calculation. + if newMemSize > 0x1FFFFFFFE0 { return 0, errGasUintOverflow } - newMemSizeWords := toWordSize(newMemSize) newMemSize = newMemSizeWords * 32 @@ -57,65 +55,45 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { return 0, nil } -func constGasFunc(gas uint64) gasFunc { - return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +// memoryCopierGas creates the gas functions for the following opcodes, and takes +// the stack position of the operand which determines the size of the data to copy +// as argument: +// CALLDATACOPY (stack position 2) +// CODECOPY (stack position 2) +// EXTCODECOPY (stack poition 3) +// RETURNDATACOPY (stack position 2) +func memoryCopierGas(stackpos int) gasFunc { + return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // Gas for expanding the memory + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + // And gas for copying data, charged per word at param.CopyGas + words, overflow := bigUint64(stack.Back(stackpos)) + if overflow { + return 0, errGasUintOverflow + } + + if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { + return 0, errGasUintOverflow + } + + if gas, overflow = math.SafeAdd(gas, words); overflow { + return 0, errGasUintOverflow + } return gas, nil } } -func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } +var ( + gasCallDataCopy = memoryCopierGas(2) + gasCodeCopy = memoryCopierGas(2) + gasExtCodeCopy = memoryCopierGas(3) + gasReturnDataCopy = memoryCopierGas(2) +) - var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - - words, overflow := bigUint64(stack.Back(2)) - if overflow { - return 0, errGasUintOverflow - } - - if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { - return 0, errGasUintOverflow - } - - if gas, overflow = math.SafeAdd(gas, words); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - - var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - - words, overflow := bigUint64(stack.Back(2)) - if overflow { - return 0, errGasUintOverflow - } - - if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { - return 0, errGasUintOverflow - } - - if gas, overflow = math.SafeAdd(gas, words); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var ( y, x = stack.Back(1), stack.Back(0) current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) @@ -184,8 +162,63 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m return params.NetSstoreDirtyGas, nil } +// 0. If *gasleft* is less than or equal to 2300, fail the current call. +// 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted. +// 2. If current value does not equal new value: +// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context): +// 2.1.1. If original value is 0, SSTORE_INIT_GAS gas is deducted. +// 2.1.2. Otherwise, SSTORE_CLEAN_GAS gas is deducted. If new value is 0, add SSTORE_CLEAR_REFUND to refund counter. +// 2.2. If original value does not equal current value (this storage slot is dirty), SSTORE_DIRTY_GAS gas is deducted. Apply both of the following clauses: +// 2.2.1. If original value is not 0: +// 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEAR_REFUND gas from refund counter. We can prove that refund counter will never go below 0. +// 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEAR_REFUND gas to refund counter. +// 2.2.2. If original value equals new value (this storage slot is reset): +// 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter. +// 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter. +func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // If we fail the minimum gas availability invariant, fail (0) + if contract.Gas <= params.SstoreSentryGasEIP2200 { + return 0, errors.New("not enough gas for reentrancy sentry") + } + // Gas sentry honoured, do the actual gas calculation based on the stored value + var ( + y, x = stack.Back(1), stack.Back(0) + current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) + ) + value := common.BigToHash(y) + + if current == value { // noop (1) + return params.SstoreNoopGasEIP2200, nil + } + original := evm.StateDB.GetCommittedState(contract.Address(), common.BigToHash(x)) + if original == current { + if original == (common.Hash{}) { // create slot (2.1.1) + return params.SstoreInitGasEIP2200, nil + } + if value == (common.Hash{}) { // delete slot (2.1.2b) + evm.StateDB.AddRefund(params.SstoreClearRefundEIP2200) + } + return params.SstoreCleanGasEIP2200, nil // write existing slot (2.1.2) + } + if original != (common.Hash{}) { + if current == (common.Hash{}) { // recreate slot (2.2.1.1) + evm.StateDB.SubRefund(params.SstoreClearRefundEIP2200) + } else if value == (common.Hash{}) { // delete slot (2.2.1.2) + evm.StateDB.AddRefund(params.SstoreClearRefundEIP2200) + } + } + if original == value { + if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1) + evm.StateDB.AddRefund(params.SstoreInitRefundEIP2200) + } else { // reset to original existing slot (2.2.2.2) + evm.StateDB.AddRefund(params.SstoreCleanRefundEIP2200) + } + } + return params.SstoreDirtyGasEIP2200, nil // dirty update (2.2) +} + func makeGasLog(n uint64) gasFunc { - return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { requestedSize, overflow := bigUint64(stack.Back(1)) if overflow { return 0, errGasUintOverflow @@ -214,17 +247,11 @@ func makeGasLog(n uint64) gasFunc { } } -func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool +func gasSha3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err } - - if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow { - return 0, errGasUintOverflow - } - wordGas, overflow := bigUint64(stack.Back(1)) if overflow { return 0, errGasUintOverflow @@ -238,117 +265,27 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return gas, nil } -func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +// pureMemoryGascost is used by several operations, which aside from their +// static cost have a dynamic cost which is solely based on the memory +// expansion +func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return memoryGasCost(mem, memorySize) +} + +var ( + gasReturn = pureMemoryGascost + gasRevert = pureMemoryGascost + gasMLoad = pureMemoryGascost + gasMStore8 = pureMemoryGascost + gasMStore = pureMemoryGascost + gasCreate = pureMemoryGascost +) + +func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err } - - var overflow bool - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - - wordGas, overflow := bigUint64(stack.Back(2)) - if overflow { - return 0, errGasUintOverflow - } - if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { - return 0, errGasUintOverflow - } - if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - - var overflow bool - if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow { - return 0, errGasUintOverflow - } - - wordGas, overflow := bigUint64(stack.Back(3)) - if overflow { - return 0, errGasUintOverflow - } - - if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { - return 0, errGasUintOverflow - } - - if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.ExtcodeHash, nil -} - -func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, errGasUintOverflow - } - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, errGasUintOverflow - } - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, errGasUintOverflow - } - if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - var overflow bool - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow { - return 0, errGasUintOverflow - } wordGas, overflow := bigUint64(stack.Back(2)) if overflow { return 0, errGasUintOverflow @@ -359,43 +296,42 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, if gas, overflow = math.SafeAdd(gas, wordGas); overflow { return 0, errGasUintOverflow } - return gas, nil } -func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.Balance, nil -} - -func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.ExtcodeSize, nil -} - -func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return gt.SLoad, nil -} - -func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) var ( - gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas + gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas overflow bool ) - if gas, overflow = math.SafeAdd(gas, GasSlowStep); overflow { + if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { return 0, errGasUintOverflow } return gas, nil } -func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) + var ( - gas = gt.Calls + gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas + overflow bool + ) + if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { + return 0, errGasUintOverflow + } + return gas, nil +} + +func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var ( + gas uint64 transfersValue = stack.Back(2).Sign() != 0 address = common.BigToAddress(stack.Back(1)) - eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) ) - if eip158 { + if evm.chainRules.IsEIP158 { if transfersValue && evm.StateDB.Empty(address) { gas += params.CallNewAccountGas } @@ -414,7 +350,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } @@ -424,21 +360,22 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return gas, nil } -func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas := gt.Calls - if stack.Back(2).Sign() != 0 { - gas += params.CallValueTransferGas - } +func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { memoryGas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err } - var overflow bool + var ( + gas uint64 + overflow bool + ) + if stack.Back(2).Sign() != 0 { + gas += params.CallValueTransferGas + } if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { return 0, errGasUintOverflow } - - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } @@ -448,88 +385,57 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, return gas, nil } -func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return memoryGasCost(mem, memorySize) +func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, errGasUintOverflow + } + return gas, nil } -func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return memoryGasCost(mem, memorySize) +func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, errGasUintOverflow + } + return gas, nil } -func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var gas uint64 // EIP150 homestead gas reprice fork: - if evm.ChainConfig().IsEIP150(evm.BlockNumber) { - gas = gt.Suicide - var ( - address = common.BigToAddress(stack.Back(0)) - eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) - ) + if evm.chainRules.IsEIP150 { + gas = params.SelfdestructGasEIP150 + var address = common.BigToAddress(stack.Back(0)) - if eip158 { + if evm.chainRules.IsEIP158 { // if empty and transfers value if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { - gas += gt.CreateBySuicide + gas += params.CreateBySelfdestructGas } } else if !evm.StateDB.Exist(address) { - gas += gt.CreateBySuicide + gas += params.CreateBySelfdestructGas } } if !evm.StateDB.HasSuicided(contract.Address()) { - evm.StateDB.AddRefund(params.SuicideRefundGas) + evm.StateDB.AddRefund(params.SelfdestructRefundGas) } return gas, nil } - -func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - var overflow bool - if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { - return 0, errGasUintOverflow - } - - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) - if err != nil { - return 0, err - } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) - if err != nil { - return 0, err - } - var overflow bool - if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { - return 0, errGasUintOverflow - } - - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) - if err != nil { - return 0, err - } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow - } - return gas, nil -} - -func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return GasFastestStep, nil -} - -func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return GasFastestStep, nil -} - -func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return GasFastestStep, nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go index 5195e716b..7b6909c92 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/instructions.go @@ -18,7 +18,6 @@ package vm import ( "errors" - "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -35,6 +34,7 @@ var ( errReturnDataOutOfBounds = errors.New("evm: return data out of bounds") errExecutionReverted = errors.New("evm: execution reverted") errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded") + errInvalidJump = errors.New("evm: invalid jump destination") ) func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { @@ -405,7 +405,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory } func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(contract.Address().Big()) + stack.push(interpreter.intPool.get().SetBytes(contract.Address().Bytes())) return nil, nil } @@ -416,12 +416,12 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo } func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(interpreter.evm.Origin.Big()) + stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Origin.Bytes())) return nil, nil } func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(contract.Caller().Big()) + stack.push(interpreter.intPool.get().SetBytes(contract.Caller().Bytes())) return nil, nil } @@ -467,7 +467,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contrac ) defer interpreter.intPool.put(memOffset, dataOffset, length, end) - if end.BitLen() > 64 || uint64(len(interpreter.returnData)) < end.Uint64() { + if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() { return nil, errReturnDataOutOfBounds } memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()]) @@ -572,7 +572,7 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, me } func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(interpreter.evm.Coinbase.Big()) + stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Coinbase.Bytes())) return nil, nil } @@ -645,8 +645,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { pos := stack.pop() if !contract.validJumpdest(pos) { - nop := contract.GetOp(pos.Uint64()) - return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) + return nil, errInvalidJump } *pc = pos.Uint64() @@ -658,8 +657,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory pos, cond := stack.pop(), stack.pop() if cond.Sign() != 0 { if !contract.validJumpdest(pos) { - nop := contract.GetOp(pos.Uint64()) - return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) + return nil, errInvalidJump } *pc = pos.Uint64() } else { @@ -696,7 +694,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor input = memory.Get(offset.Int64(), size.Int64()) gas = contract.Gas ) - if interpreter.evm.ChainConfig().IsEIP150(interpreter.evm.BlockNumber) { + if interpreter.evm.chainRules.IsEIP150 { gas -= gas / 64 } @@ -706,12 +704,12 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must // ignore this error and pretend the operation was successful. - if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas { + if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas { stack.push(interpreter.intPool.getZero()) } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { stack.push(interpreter.intPool.getZero()) } else { - stack.push(addr.Big()) + stack.push(interpreter.intPool.get().SetBytes(addr.Bytes())) } contract.Gas += returnGas interpreter.intPool.put(value, offset, size) @@ -739,7 +737,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo if suberr != nil { stack.push(interpreter.intPool.getZero()) } else { - stack.push(addr.Big()) + stack.push(interpreter.intPool.get().SetBytes(addr.Bytes())) } contract.Gas += returnGas interpreter.intPool.put(endowment, offset, size, salt) @@ -912,6 +910,21 @@ func makeLog(size int) executionFunc { } } +// opPush1 is a specialized version of pushN +func opPush1(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + var ( + codeLen = uint64(len(contract.Code)) + integer = interpreter.intPool.get() + ) + *pc += 1 + if *pc < codeLen { + stack.push(integer.SetUint64(uint64(contract.Code[*pc]))) + } else { + stack.push(integer.SetUint64(0)) + } + return nil, nil +} + // make push instruction function func makePush(size uint64, pushByteSize int) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/interface.go b/vendor/github.com/ethereum/go-ethereum/core/vm/interface.go index fc15082f1..dd401466a 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/interface.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/interface.go @@ -63,7 +63,7 @@ type StateDB interface { AddLog(*types.Log) AddPreimage(common.Hash, []byte) - ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) + ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error } // CallContext provides a basic interface for the EVM calling conventions. The EVM diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go b/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go index 952d96dd4..fe06492de 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/interpreter.go @@ -23,29 +23,22 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/log" ) // Config are the configuration options for the Interpreter type Config struct { - // Debug enabled debugging Interpreter options - Debug bool - // Tracer is the op code logger - Tracer Tracer - // NoRecursion disabled Interpreter call, callcode, - // delegate call and create. - NoRecursion bool - // Enable recording of SHA3/keccak preimages - EnablePreimageRecording bool - // JumpTable contains the EVM instruction table. This - // may be left uninitialised and will be set to the default - // table. - JumpTable [256]operation + Debug bool // Enables debugging + Tracer Tracer // Opcode logger + NoRecursion bool // Disables call, callcode, delegate call and create + EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages - // Type of the EWASM interpreter - EWASMInterpreter string - // Type of the EVM interpreter - EVMInterpreter string + JumpTable [256]operation // EVM instruction table, automatically populated if unset + + EWASMInterpreter string // External EWASM interpreter options + EVMInterpreter string // External EVM interpreter options + + ExtraEips []int // Additional EIPS that are to be enabled } // Interpreter is used to run Ethereum based contracts and will utilise the @@ -80,9 +73,8 @@ type keccakState interface { // EVMInterpreter represents an EVM interpreter type EVMInterpreter struct { - evm *EVM - cfg Config - gasTable params.GasTable + evm *EVM + cfg Config intPool *intPool @@ -99,41 +91,39 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { // the jump table was initialised. If it was not // we'll set the default jump table. if !cfg.JumpTable[STOP].valid { + var jt JumpTable switch { - case evm.ChainConfig().IsConstantinople(evm.BlockNumber): - cfg.JumpTable = constantinopleInstructionSet - case evm.ChainConfig().IsByzantium(evm.BlockNumber): - cfg.JumpTable = byzantiumInstructionSet - case evm.ChainConfig().IsHomestead(evm.BlockNumber): - cfg.JumpTable = homesteadInstructionSet + case evm.chainRules.IsIstanbul: + jt = istanbulInstructionSet + case evm.chainRules.IsConstantinople: + jt = constantinopleInstructionSet + case evm.chainRules.IsByzantium: + jt = byzantiumInstructionSet + case evm.chainRules.IsEIP158: + jt = spuriousDragonInstructionSet + case evm.chainRules.IsEIP150: + jt = tangerineWhistleInstructionSet + case evm.chainRules.IsHomestead: + jt = homesteadInstructionSet default: - cfg.JumpTable = frontierInstructionSet + jt = frontierInstructionSet } + for i, eip := range cfg.ExtraEips { + if err := EnableEIP(eip, &jt); err != nil { + // Disable it, so caller can check if it's activated or not + cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...) + log.Error("EIP activation failed", "eip", eip, "error", err) + } + } + cfg.JumpTable = jt } return &EVMInterpreter{ - evm: evm, - cfg: cfg, - gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), + evm: evm, + cfg: cfg, } } -func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { - if in.evm.chainRules.IsByzantium { - if in.readOnly { - // If the interpreter is operating in readonly mode, make sure no - // state-modifying operation is performed. The 3rd stack item - // for a call operation is the value. Transferring value from one - // account to the others means the state is modified and should also - // return with an error. - if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) { - return errWriteProtection - } - } - } - return nil -} - // Run loops and evaluates the contract's code with the given input data and returns // the return byte-slice and an error if one occurred. // @@ -182,6 +172,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( pcCopy uint64 // needed for the deferred Tracer gasCopy uint64 // for Tracer to log gas remaining before execution logged bool // deferred Tracer should ignore already logged steps + res []byte // result of the opcode execution function ) contract.Input = input @@ -216,19 +207,36 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( if !operation.valid { return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) } - if err := operation.validateStack(stack); err != nil { - return nil, err + // Validate stack + if sLen := stack.len(); sLen < operation.minStack { + return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack) + } else if sLen > operation.maxStack { + return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack) } // If the operation is valid, enforce and write restrictions - if err := in.enforceRestrictions(op, operation, stack); err != nil { - return nil, err + if in.readOnly && in.evm.chainRules.IsByzantium { + // If the interpreter is operating in readonly mode, make sure no + // state-modifying operation is performed. The 3rd stack item + // for a call operation is the value. Transferring value from one + // account to the others means the state is modified and should also + // return with an error. + if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { + return nil, errWriteProtection + } + } + // Static portion of gas + cost = operation.constantGas // For tracing + if !contract.UseGas(operation.constantGas) { + return nil, ErrOutOfGas } var memorySize uint64 // calculate the new memory size and expand the memory to fit // the operation + // Memory check needs to be done prior to evaluating the dynamic gas portion, + // to detect calculation overflows if operation.memorySize != nil { - memSize, overflow := bigUint64(operation.memorySize(stack)) + memSize, overflow := operation.memorySize(stack) if overflow { return nil, errGasUintOverflow } @@ -238,11 +246,16 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( return nil, errGasUintOverflow } } + // Dynamic portion of gas // consume the gas and return an error if not enough gas is available. // cost is explicitly set so that the capture state defer method can get the proper cost - cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize) - if err != nil || !contract.UseGas(cost) { - return nil, ErrOutOfGas + if operation.dynamicGas != nil { + var dynamicCost uint64 + dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize) + cost += dynamicCost // total cost, for debug tracing + if err != nil || !contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } } if memorySize > 0 { mem.Resize(memorySize) @@ -254,7 +267,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } // execute the operation - res, err := operation.execute(&pc, in, contract, mem, stack) + res, err = operation.execute(&pc, in, contract, mem, stack) // verifyPool is a build flag. Pool verification makes sure the integrity // of the integer pool by comparing values to a default value. if verifyPool { diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go index deedf70cd..b26b55284 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/jump_table.go @@ -18,27 +18,30 @@ package vm import ( "errors" - "math/big" "github.com/ethereum/go-ethereum/params" ) type ( - executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) - gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 - stackValidationFunc func(*Stack) error - memorySizeFunc func(*Stack) *big.Int + executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) + gasFunc func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 + // memorySizeFunc returns the required size, and whether the operation overflowed a uint64 + memorySizeFunc func(*Stack) (size uint64, overflow bool) ) var errGasUintOverflow = errors.New("gas uint64 overflow") type operation struct { // execute is the operation function - execute executionFunc - // gasCost is the gas function and returns the gas required for execution - gasCost gasFunc - // validateStack validates the stack (size) for the operation - validateStack stackValidationFunc + execute executionFunc + constantGas uint64 + dynamicGas gasFunc + // minStack tells how many stack items are required + minStack int + // maxStack specifies the max length the stack can have for this operation + // to not overflow the stack. + maxStack int + // memorySize returns the memory size required for the operation memorySize memorySizeFunc @@ -51,916 +54,1106 @@ type operation struct { } var ( - frontierInstructionSet = newFrontierInstructionSet() - homesteadInstructionSet = newHomesteadInstructionSet() - byzantiumInstructionSet = newByzantiumInstructionSet() - constantinopleInstructionSet = newConstantinopleInstructionSet() + frontierInstructionSet = newFrontierInstructionSet() + homesteadInstructionSet = newHomesteadInstructionSet() + tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet() + spuriousDragonInstructionSet = newSpuriousDragonInstructionSet() + byzantiumInstructionSet = newByzantiumInstructionSet() + constantinopleInstructionSet = newConstantinopleInstructionSet() + istanbulInstructionSet = newIstanbulInstructionSet() ) -// NewConstantinopleInstructionSet returns the frontier, homestead +// JumpTable contains the EVM opcodes supported at a given fork. +type JumpTable [256]operation + +// newIstanbulInstructionSet returns the frontier, homestead +// byzantium, contantinople and petersburg instructions. +func newIstanbulInstructionSet() JumpTable { + instructionSet := newConstantinopleInstructionSet() + + enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344 + enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884 + enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200 + + return instructionSet +} + +// newConstantinopleInstructionSet returns the frontier, homestead // byzantium and contantinople instructions. -func newConstantinopleInstructionSet() [256]operation { - // instructions that can be executed during the byzantium phase. +func newConstantinopleInstructionSet() JumpTable { instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = operation{ - execute: opSHL, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSHL, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, } instructionSet[SHR] = operation{ - execute: opSHR, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSHR, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, } instructionSet[SAR] = operation{ - execute: opSAR, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSAR, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, } instructionSet[EXTCODEHASH] = operation{ - execute: opExtCodeHash, - gasCost: gasExtCodeHash, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opExtCodeHash, + constantGas: params.ExtcodeHashGasConstantinople, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, } instructionSet[CREATE2] = operation{ - execute: opCreate2, - gasCost: gasCreate2, - validateStack: makeStackFunc(4, 1), - memorySize: memoryCreate2, - valid: true, - writes: true, - returns: true, + execute: opCreate2, + constantGas: params.Create2Gas, + dynamicGas: gasCreate2, + minStack: minStack(4, 1), + maxStack: maxStack(4, 1), + memorySize: memoryCreate2, + valid: true, + writes: true, + returns: true, } return instructionSet } -// NewByzantiumInstructionSet returns the frontier, homestead and +// newByzantiumInstructionSet returns the frontier, homestead and // byzantium instructions. -func newByzantiumInstructionSet() [256]operation { - // instructions that can be executed during the homestead phase. - instructionSet := newHomesteadInstructionSet() +func newByzantiumInstructionSet() JumpTable { + instructionSet := newSpuriousDragonInstructionSet() instructionSet[STATICCALL] = operation{ - execute: opStaticCall, - gasCost: gasStaticCall, - validateStack: makeStackFunc(6, 1), - memorySize: memoryStaticCall, - valid: true, - returns: true, + execute: opStaticCall, + constantGas: params.CallGasEIP150, + dynamicGas: gasStaticCall, + minStack: minStack(6, 1), + maxStack: maxStack(6, 1), + memorySize: memoryStaticCall, + valid: true, + returns: true, } instructionSet[RETURNDATASIZE] = operation{ - execute: opReturnDataSize, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opReturnDataSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, } instructionSet[RETURNDATACOPY] = operation{ - execute: opReturnDataCopy, - gasCost: gasReturnDataCopy, - validateStack: makeStackFunc(3, 0), - memorySize: memoryReturnDataCopy, - valid: true, + execute: opReturnDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasReturnDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryReturnDataCopy, + valid: true, } instructionSet[REVERT] = operation{ - execute: opRevert, - gasCost: gasRevert, - validateStack: makeStackFunc(2, 0), - memorySize: memoryRevert, - valid: true, - reverts: true, - returns: true, + execute: opRevert, + dynamicGas: gasRevert, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryRevert, + valid: true, + reverts: true, + returns: true, } return instructionSet } -// NewHomesteadInstructionSet returns the frontier and homestead +// EIP 158 a.k.a Spurious Dragon +func newSpuriousDragonInstructionSet() JumpTable { + instructionSet := newTangerineWhistleInstructionSet() + instructionSet[EXP].dynamicGas = gasExpEIP158 + return instructionSet + +} + +// EIP 150 a.k.a Tangerine Whistle +func newTangerineWhistleInstructionSet() JumpTable { + instructionSet := newHomesteadInstructionSet() + instructionSet[BALANCE].constantGas = params.BalanceGasEIP150 + instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEIP150 + instructionSet[SLOAD].constantGas = params.SloadGasEIP150 + instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEIP150 + instructionSet[CALL].constantGas = params.CallGasEIP150 + instructionSet[CALLCODE].constantGas = params.CallGasEIP150 + instructionSet[DELEGATECALL].constantGas = params.CallGasEIP150 + return instructionSet +} + +// newHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. -func newHomesteadInstructionSet() [256]operation { +func newHomesteadInstructionSet() JumpTable { instructionSet := newFrontierInstructionSet() instructionSet[DELEGATECALL] = operation{ - execute: opDelegateCall, - gasCost: gasDelegateCall, - validateStack: makeStackFunc(6, 1), - memorySize: memoryDelegateCall, - valid: true, - returns: true, + execute: opDelegateCall, + dynamicGas: gasDelegateCall, + constantGas: params.CallGasFrontier, + minStack: minStack(6, 1), + maxStack: maxStack(6, 1), + memorySize: memoryDelegateCall, + valid: true, + returns: true, } return instructionSet } -// NewFrontierInstructionSet returns the frontier instructions +// newFrontierInstructionSet returns the frontier instructions // that can be executed during the frontier phase. -func newFrontierInstructionSet() [256]operation { - return [256]operation{ +func newFrontierInstructionSet() JumpTable { + return JumpTable{ STOP: { - execute: opStop, - gasCost: constGasFunc(0), - validateStack: makeStackFunc(0, 0), - halts: true, - valid: true, + execute: opStop, + constantGas: 0, + minStack: minStack(0, 0), + maxStack: maxStack(0, 0), + halts: true, + valid: true, }, ADD: { - execute: opAdd, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opAdd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, MUL: { - execute: opMul, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opMul, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SUB: { - execute: opSub, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSub, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, DIV: { - execute: opDiv, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opDiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SDIV: { - execute: opSdiv, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSdiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, MOD: { - execute: opMod, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opMod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SMOD: { - execute: opSmod, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSmod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, ADDMOD: { - execute: opAddmod, - gasCost: constGasFunc(GasMidStep), - validateStack: makeStackFunc(3, 1), - valid: true, + execute: opAddmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + valid: true, }, MULMOD: { - execute: opMulmod, - gasCost: constGasFunc(GasMidStep), - validateStack: makeStackFunc(3, 1), - valid: true, + execute: opMulmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + valid: true, }, EXP: { - execute: opExp, - gasCost: gasExp, - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opExp, + dynamicGas: gasExpFrontier, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SIGNEXTEND: { - execute: opSignExtend, - gasCost: constGasFunc(GasFastStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSignExtend, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, LT: { - execute: opLt, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opLt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, GT: { - execute: opGt, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opGt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SLT: { - execute: opSlt, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSlt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SGT: { - execute: opSgt, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opSgt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, EQ: { - execute: opEq, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opEq, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, ISZERO: { - execute: opIszero, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opIszero, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, AND: { - execute: opAnd, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opAnd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, XOR: { - execute: opXor, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opXor, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, OR: { - execute: opOr, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opOr, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, NOT: { - execute: opNot, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opNot, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, BYTE: { - execute: opByte, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opByte, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SHA3: { - execute: opSha3, - gasCost: gasSha3, - validateStack: makeStackFunc(2, 1), - memorySize: memorySha3, - valid: true, + execute: opSha3, + constantGas: params.Sha3Gas, + dynamicGas: gasSha3, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + memorySize: memorySha3, + valid: true, }, ADDRESS: { - execute: opAddress, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opAddress, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, BALANCE: { - execute: opBalance, - gasCost: gasBalance, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opBalance, + constantGas: params.BalanceGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, ORIGIN: { - execute: opOrigin, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opOrigin, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLER: { - execute: opCaller, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opCaller, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLVALUE: { - execute: opCallValue, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opCallValue, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLDATALOAD: { - execute: opCallDataLoad, - gasCost: constGasFunc(GasFastestStep), - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opCallDataLoad, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, CALLDATASIZE: { - execute: opCallDataSize, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opCallDataSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLDATACOPY: { - execute: opCallDataCopy, - gasCost: gasCallDataCopy, - validateStack: makeStackFunc(3, 0), - memorySize: memoryCallDataCopy, - valid: true, + execute: opCallDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasCallDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCallDataCopy, + valid: true, }, CODESIZE: { - execute: opCodeSize, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opCodeSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CODECOPY: { - execute: opCodeCopy, - gasCost: gasCodeCopy, - validateStack: makeStackFunc(3, 0), - memorySize: memoryCodeCopy, - valid: true, + execute: opCodeCopy, + constantGas: GasFastestStep, + dynamicGas: gasCodeCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCodeCopy, + valid: true, }, GASPRICE: { - execute: opGasprice, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opGasprice, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, EXTCODESIZE: { - execute: opExtCodeSize, - gasCost: gasExtCodeSize, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opExtCodeSize, + constantGas: params.ExtcodeSizeGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, EXTCODECOPY: { - execute: opExtCodeCopy, - gasCost: gasExtCodeCopy, - validateStack: makeStackFunc(4, 0), - memorySize: memoryExtCodeCopy, - valid: true, + execute: opExtCodeCopy, + constantGas: params.ExtcodeCopyBaseFrontier, + dynamicGas: gasExtCodeCopy, + minStack: minStack(4, 0), + maxStack: maxStack(4, 0), + memorySize: memoryExtCodeCopy, + valid: true, }, BLOCKHASH: { - execute: opBlockhash, - gasCost: constGasFunc(GasExtStep), - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opBlockhash, + constantGas: GasExtStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, COINBASE: { - execute: opCoinbase, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opCoinbase, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, TIMESTAMP: { - execute: opTimestamp, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opTimestamp, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, NUMBER: { - execute: opNumber, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opNumber, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, DIFFICULTY: { - execute: opDifficulty, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opDifficulty, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, GASLIMIT: { - execute: opGasLimit, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opGasLimit, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, POP: { - execute: opPop, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(1, 0), - valid: true, + execute: opPop, + constantGas: GasQuickStep, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + valid: true, }, MLOAD: { - execute: opMload, - gasCost: gasMLoad, - validateStack: makeStackFunc(1, 1), - memorySize: memoryMLoad, - valid: true, + execute: opMload, + constantGas: GasFastestStep, + dynamicGas: gasMLoad, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + memorySize: memoryMLoad, + valid: true, }, MSTORE: { - execute: opMstore, - gasCost: gasMStore, - validateStack: makeStackFunc(2, 0), - memorySize: memoryMStore, - valid: true, + execute: opMstore, + constantGas: GasFastestStep, + dynamicGas: gasMStore, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryMStore, + valid: true, }, MSTORE8: { - execute: opMstore8, - gasCost: gasMStore8, - memorySize: memoryMStore8, - validateStack: makeStackFunc(2, 0), + execute: opMstore8, + constantGas: GasFastestStep, + dynamicGas: gasMStore8, + memorySize: memoryMStore8, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), valid: true, }, SLOAD: { - execute: opSload, - gasCost: gasSLoad, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opSload, + constantGas: params.SloadGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, SSTORE: { - execute: opSstore, - gasCost: gasSStore, - validateStack: makeStackFunc(2, 0), - valid: true, - writes: true, + execute: opSstore, + dynamicGas: gasSStore, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + valid: true, + writes: true, }, JUMP: { - execute: opJump, - gasCost: constGasFunc(GasMidStep), - validateStack: makeStackFunc(1, 0), - jumps: true, - valid: true, + execute: opJump, + constantGas: GasMidStep, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + jumps: true, + valid: true, }, JUMPI: { - execute: opJumpi, - gasCost: constGasFunc(GasSlowStep), - validateStack: makeStackFunc(2, 0), - jumps: true, - valid: true, + execute: opJumpi, + constantGas: GasSlowStep, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + jumps: true, + valid: true, }, PC: { - execute: opPc, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opPc, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, MSIZE: { - execute: opMsize, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opMsize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, GAS: { - execute: opGas, - gasCost: constGasFunc(GasQuickStep), - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opGas, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, JUMPDEST: { - execute: opJumpdest, - gasCost: constGasFunc(params.JumpdestGas), - validateStack: makeStackFunc(0, 0), - valid: true, + execute: opJumpdest, + constantGas: params.JumpdestGas, + minStack: minStack(0, 0), + maxStack: maxStack(0, 0), + valid: true, }, PUSH1: { - execute: makePush(1, 1), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: opPush1, + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH2: { - execute: makePush(2, 2), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(2, 2), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH3: { - execute: makePush(3, 3), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(3, 3), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH4: { - execute: makePush(4, 4), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(4, 4), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH5: { - execute: makePush(5, 5), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(5, 5), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH6: { - execute: makePush(6, 6), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(6, 6), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH7: { - execute: makePush(7, 7), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(7, 7), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH8: { - execute: makePush(8, 8), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(8, 8), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH9: { - execute: makePush(9, 9), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(9, 9), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH10: { - execute: makePush(10, 10), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(10, 10), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH11: { - execute: makePush(11, 11), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(11, 11), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH12: { - execute: makePush(12, 12), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(12, 12), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH13: { - execute: makePush(13, 13), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(13, 13), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH14: { - execute: makePush(14, 14), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(14, 14), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH15: { - execute: makePush(15, 15), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(15, 15), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH16: { - execute: makePush(16, 16), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(16, 16), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH17: { - execute: makePush(17, 17), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(17, 17), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH18: { - execute: makePush(18, 18), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(18, 18), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH19: { - execute: makePush(19, 19), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(19, 19), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH20: { - execute: makePush(20, 20), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(20, 20), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH21: { - execute: makePush(21, 21), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(21, 21), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH22: { - execute: makePush(22, 22), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(22, 22), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH23: { - execute: makePush(23, 23), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(23, 23), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH24: { - execute: makePush(24, 24), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(24, 24), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH25: { - execute: makePush(25, 25), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(25, 25), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH26: { - execute: makePush(26, 26), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(26, 26), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH27: { - execute: makePush(27, 27), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(27, 27), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH28: { - execute: makePush(28, 28), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(28, 28), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH29: { - execute: makePush(29, 29), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(29, 29), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH30: { - execute: makePush(30, 30), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(30, 30), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH31: { - execute: makePush(31, 31), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(31, 31), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH32: { - execute: makePush(32, 32), - gasCost: gasPush, - validateStack: makeStackFunc(0, 1), - valid: true, + execute: makePush(32, 32), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, DUP1: { - execute: makeDup(1), - gasCost: gasDup, - validateStack: makeDupStackFunc(1), - valid: true, + execute: makeDup(1), + constantGas: GasFastestStep, + minStack: minDupStack(1), + maxStack: maxDupStack(1), + valid: true, }, DUP2: { - execute: makeDup(2), - gasCost: gasDup, - validateStack: makeDupStackFunc(2), - valid: true, + execute: makeDup(2), + constantGas: GasFastestStep, + minStack: minDupStack(2), + maxStack: maxDupStack(2), + valid: true, }, DUP3: { - execute: makeDup(3), - gasCost: gasDup, - validateStack: makeDupStackFunc(3), - valid: true, + execute: makeDup(3), + constantGas: GasFastestStep, + minStack: minDupStack(3), + maxStack: maxDupStack(3), + valid: true, }, DUP4: { - execute: makeDup(4), - gasCost: gasDup, - validateStack: makeDupStackFunc(4), - valid: true, + execute: makeDup(4), + constantGas: GasFastestStep, + minStack: minDupStack(4), + maxStack: maxDupStack(4), + valid: true, }, DUP5: { - execute: makeDup(5), - gasCost: gasDup, - validateStack: makeDupStackFunc(5), - valid: true, + execute: makeDup(5), + constantGas: GasFastestStep, + minStack: minDupStack(5), + maxStack: maxDupStack(5), + valid: true, }, DUP6: { - execute: makeDup(6), - gasCost: gasDup, - validateStack: makeDupStackFunc(6), - valid: true, + execute: makeDup(6), + constantGas: GasFastestStep, + minStack: minDupStack(6), + maxStack: maxDupStack(6), + valid: true, }, DUP7: { - execute: makeDup(7), - gasCost: gasDup, - validateStack: makeDupStackFunc(7), - valid: true, + execute: makeDup(7), + constantGas: GasFastestStep, + minStack: minDupStack(7), + maxStack: maxDupStack(7), + valid: true, }, DUP8: { - execute: makeDup(8), - gasCost: gasDup, - validateStack: makeDupStackFunc(8), - valid: true, + execute: makeDup(8), + constantGas: GasFastestStep, + minStack: minDupStack(8), + maxStack: maxDupStack(8), + valid: true, }, DUP9: { - execute: makeDup(9), - gasCost: gasDup, - validateStack: makeDupStackFunc(9), - valid: true, + execute: makeDup(9), + constantGas: GasFastestStep, + minStack: minDupStack(9), + maxStack: maxDupStack(9), + valid: true, }, DUP10: { - execute: makeDup(10), - gasCost: gasDup, - validateStack: makeDupStackFunc(10), - valid: true, + execute: makeDup(10), + constantGas: GasFastestStep, + minStack: minDupStack(10), + maxStack: maxDupStack(10), + valid: true, }, DUP11: { - execute: makeDup(11), - gasCost: gasDup, - validateStack: makeDupStackFunc(11), - valid: true, + execute: makeDup(11), + constantGas: GasFastestStep, + minStack: minDupStack(11), + maxStack: maxDupStack(11), + valid: true, }, DUP12: { - execute: makeDup(12), - gasCost: gasDup, - validateStack: makeDupStackFunc(12), - valid: true, + execute: makeDup(12), + constantGas: GasFastestStep, + minStack: minDupStack(12), + maxStack: maxDupStack(12), + valid: true, }, DUP13: { - execute: makeDup(13), - gasCost: gasDup, - validateStack: makeDupStackFunc(13), - valid: true, + execute: makeDup(13), + constantGas: GasFastestStep, + minStack: minDupStack(13), + maxStack: maxDupStack(13), + valid: true, }, DUP14: { - execute: makeDup(14), - gasCost: gasDup, - validateStack: makeDupStackFunc(14), - valid: true, + execute: makeDup(14), + constantGas: GasFastestStep, + minStack: minDupStack(14), + maxStack: maxDupStack(14), + valid: true, }, DUP15: { - execute: makeDup(15), - gasCost: gasDup, - validateStack: makeDupStackFunc(15), - valid: true, + execute: makeDup(15), + constantGas: GasFastestStep, + minStack: minDupStack(15), + maxStack: maxDupStack(15), + valid: true, }, DUP16: { - execute: makeDup(16), - gasCost: gasDup, - validateStack: makeDupStackFunc(16), - valid: true, + execute: makeDup(16), + constantGas: GasFastestStep, + minStack: minDupStack(16), + maxStack: maxDupStack(16), + valid: true, }, SWAP1: { - execute: makeSwap(1), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(2), - valid: true, + execute: makeSwap(1), + constantGas: GasFastestStep, + minStack: minSwapStack(2), + maxStack: maxSwapStack(2), + valid: true, }, SWAP2: { - execute: makeSwap(2), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(3), - valid: true, + execute: makeSwap(2), + constantGas: GasFastestStep, + minStack: minSwapStack(3), + maxStack: maxSwapStack(3), + valid: true, }, SWAP3: { - execute: makeSwap(3), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(4), - valid: true, + execute: makeSwap(3), + constantGas: GasFastestStep, + minStack: minSwapStack(4), + maxStack: maxSwapStack(4), + valid: true, }, SWAP4: { - execute: makeSwap(4), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(5), - valid: true, + execute: makeSwap(4), + constantGas: GasFastestStep, + minStack: minSwapStack(5), + maxStack: maxSwapStack(5), + valid: true, }, SWAP5: { - execute: makeSwap(5), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(6), - valid: true, + execute: makeSwap(5), + constantGas: GasFastestStep, + minStack: minSwapStack(6), + maxStack: maxSwapStack(6), + valid: true, }, SWAP6: { - execute: makeSwap(6), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(7), - valid: true, + execute: makeSwap(6), + constantGas: GasFastestStep, + minStack: minSwapStack(7), + maxStack: maxSwapStack(7), + valid: true, }, SWAP7: { - execute: makeSwap(7), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(8), - valid: true, + execute: makeSwap(7), + constantGas: GasFastestStep, + minStack: minSwapStack(8), + maxStack: maxSwapStack(8), + valid: true, }, SWAP8: { - execute: makeSwap(8), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(9), - valid: true, + execute: makeSwap(8), + constantGas: GasFastestStep, + minStack: minSwapStack(9), + maxStack: maxSwapStack(9), + valid: true, }, SWAP9: { - execute: makeSwap(9), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(10), - valid: true, + execute: makeSwap(9), + constantGas: GasFastestStep, + minStack: minSwapStack(10), + maxStack: maxSwapStack(10), + valid: true, }, SWAP10: { - execute: makeSwap(10), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(11), - valid: true, + execute: makeSwap(10), + constantGas: GasFastestStep, + minStack: minSwapStack(11), + maxStack: maxSwapStack(11), + valid: true, }, SWAP11: { - execute: makeSwap(11), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(12), - valid: true, + execute: makeSwap(11), + constantGas: GasFastestStep, + minStack: minSwapStack(12), + maxStack: maxSwapStack(12), + valid: true, }, SWAP12: { - execute: makeSwap(12), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(13), - valid: true, + execute: makeSwap(12), + constantGas: GasFastestStep, + minStack: minSwapStack(13), + maxStack: maxSwapStack(13), + valid: true, }, SWAP13: { - execute: makeSwap(13), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(14), - valid: true, + execute: makeSwap(13), + constantGas: GasFastestStep, + minStack: minSwapStack(14), + maxStack: maxSwapStack(14), + valid: true, }, SWAP14: { - execute: makeSwap(14), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(15), - valid: true, + execute: makeSwap(14), + constantGas: GasFastestStep, + minStack: minSwapStack(15), + maxStack: maxSwapStack(15), + valid: true, }, SWAP15: { - execute: makeSwap(15), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(16), - valid: true, + execute: makeSwap(15), + constantGas: GasFastestStep, + minStack: minSwapStack(16), + maxStack: maxSwapStack(16), + valid: true, }, SWAP16: { - execute: makeSwap(16), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(17), - valid: true, + execute: makeSwap(16), + constantGas: GasFastestStep, + minStack: minSwapStack(17), + maxStack: maxSwapStack(17), + valid: true, }, LOG0: { - execute: makeLog(0), - gasCost: makeGasLog(0), - validateStack: makeStackFunc(2, 0), - memorySize: memoryLog, - valid: true, - writes: true, + execute: makeLog(0), + dynamicGas: makeGasLog(0), + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryLog, + valid: true, + writes: true, }, LOG1: { - execute: makeLog(1), - gasCost: makeGasLog(1), - validateStack: makeStackFunc(3, 0), - memorySize: memoryLog, - valid: true, - writes: true, + execute: makeLog(1), + dynamicGas: makeGasLog(1), + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryLog, + valid: true, + writes: true, }, LOG2: { - execute: makeLog(2), - gasCost: makeGasLog(2), - validateStack: makeStackFunc(4, 0), - memorySize: memoryLog, - valid: true, - writes: true, + execute: makeLog(2), + dynamicGas: makeGasLog(2), + minStack: minStack(4, 0), + maxStack: maxStack(4, 0), + memorySize: memoryLog, + valid: true, + writes: true, }, LOG3: { - execute: makeLog(3), - gasCost: makeGasLog(3), - validateStack: makeStackFunc(5, 0), - memorySize: memoryLog, - valid: true, - writes: true, + execute: makeLog(3), + dynamicGas: makeGasLog(3), + minStack: minStack(5, 0), + maxStack: maxStack(5, 0), + memorySize: memoryLog, + valid: true, + writes: true, }, LOG4: { - execute: makeLog(4), - gasCost: makeGasLog(4), - validateStack: makeStackFunc(6, 0), - memorySize: memoryLog, - valid: true, - writes: true, + execute: makeLog(4), + dynamicGas: makeGasLog(4), + minStack: minStack(6, 0), + maxStack: maxStack(6, 0), + memorySize: memoryLog, + valid: true, + writes: true, }, CREATE: { - execute: opCreate, - gasCost: gasCreate, - validateStack: makeStackFunc(3, 1), - memorySize: memoryCreate, - valid: true, - writes: true, - returns: true, + execute: opCreate, + constantGas: params.CreateGas, + dynamicGas: gasCreate, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + memorySize: memoryCreate, + valid: true, + writes: true, + returns: true, }, CALL: { - execute: opCall, - gasCost: gasCall, - validateStack: makeStackFunc(7, 1), - memorySize: memoryCall, - valid: true, - returns: true, + execute: opCall, + constantGas: params.CallGasFrontier, + dynamicGas: gasCall, + minStack: minStack(7, 1), + maxStack: maxStack(7, 1), + memorySize: memoryCall, + valid: true, + returns: true, }, CALLCODE: { - execute: opCallCode, - gasCost: gasCallCode, - validateStack: makeStackFunc(7, 1), - memorySize: memoryCall, - valid: true, - returns: true, + execute: opCallCode, + constantGas: params.CallGasFrontier, + dynamicGas: gasCallCode, + minStack: minStack(7, 1), + maxStack: maxStack(7, 1), + memorySize: memoryCall, + valid: true, + returns: true, }, RETURN: { - execute: opReturn, - gasCost: gasReturn, - validateStack: makeStackFunc(2, 0), - memorySize: memoryReturn, - halts: true, - valid: true, + execute: opReturn, + dynamicGas: gasReturn, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryReturn, + halts: true, + valid: true, }, SELFDESTRUCT: { - execute: opSuicide, - gasCost: gasSuicide, - validateStack: makeStackFunc(1, 0), - halts: true, - valid: true, - writes: true, + execute: opSuicide, + dynamicGas: gasSelfdestruct, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + halts: true, + valid: true, + writes: true, }, } } diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/logger.go b/vendor/github.com/ethereum/go-ethereum/core/vm/logger.go index 1733bf270..262ee5cc3 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/logger.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/logger.go @@ -158,7 +158,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui ) l.changedValues[contract.Address()][address] = value } - // Copy a snapstot of the current memory state to a new buffer + // Copy a snapshot of the current memory state to a new buffer var mem []byte if !l.cfg.DisableMemory { mem = make([]byte, len(memory.Data())) @@ -177,7 +177,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui if !l.cfg.DisableStorage { storage = l.changedValues[contract.Address()].Copy() } - // create a new snaptshot of the EVM. + // create a new snapshot of the EVM. log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, storage, depth, env.StateDB.GetRefund(), err} l.logs = append(l.logs, log) diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/logger_json.go b/vendor/github.com/ethereum/go-ethereum/core/vm/logger_json.go index ff379a4ef..04a83d066 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/logger_json.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/logger_json.go @@ -1,18 +1,18 @@ // Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. +// This file is part of the go-ethereum library. // -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // -// go-ethereum is distributed in the hope that it will be useful, +// The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// GNU Lesser General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see . +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . package vm diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go index 8fa6c90ca..4fcb41442 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/memory_table.go @@ -16,82 +16,98 @@ package vm -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common/math" -) - -func memorySha3(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(1)) +func memorySha3(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryCallDataCopy(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(2)) +func memoryCallDataCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryReturnDataCopy(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(2)) +func memoryReturnDataCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryCodeCopy(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(2)) +func memoryCodeCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryExtCodeCopy(stack *Stack) *big.Int { - return calcMemSize(stack.Back(1), stack.Back(3)) +func memoryExtCodeCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(3)) } -func memoryMLoad(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), big.NewInt(32)) +func memoryMLoad(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 32) } -func memoryMStore8(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), big.NewInt(1)) +func memoryMStore8(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 1) } -func memoryMStore(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), big.NewInt(32)) +func memoryMStore(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 32) } -func memoryCreate(stack *Stack) *big.Int { - return calcMemSize(stack.Back(1), stack.Back(2)) +func memoryCreate(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(2)) } -func memoryCreate2(stack *Stack) *big.Int { - return calcMemSize(stack.Back(1), stack.Back(2)) +func memoryCreate2(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(2)) } -func memoryCall(stack *Stack) *big.Int { - x := calcMemSize(stack.Back(5), stack.Back(6)) - y := calcMemSize(stack.Back(3), stack.Back(4)) - - return math.BigMax(x, y) +func memoryCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(5), stack.Back(6)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(3), stack.Back(4)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false +} +func memoryDelegateCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(2), stack.Back(3)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false } -func memoryDelegateCall(stack *Stack) *big.Int { - x := calcMemSize(stack.Back(4), stack.Back(5)) - y := calcMemSize(stack.Back(2), stack.Back(3)) - - return math.BigMax(x, y) +func memoryStaticCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(2), stack.Back(3)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false } -func memoryStaticCall(stack *Stack) *big.Int { - x := calcMemSize(stack.Back(4), stack.Back(5)) - y := calcMemSize(stack.Back(2), stack.Back(3)) - - return math.BigMax(x, y) +func memoryReturn(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryReturn(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(1)) +func memoryRevert(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryRevert(stack *Stack) *big.Int { - return calcMemSize(stack.Back(0), stack.Back(1)) -} - -func memoryLog(stack *Stack) *big.Int { - mSize, mStart := stack.Back(1), stack.Back(0) - return calcMemSize(mStart, mSize) +func memoryLog(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) } diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/opcodes.go b/vendor/github.com/ethereum/go-ethereum/core/vm/opcodes.go index 4349ffd29..ba0ba01b8 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/opcodes.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/opcodes.go @@ -101,6 +101,8 @@ const ( NUMBER DIFFICULTY GASLIMIT + CHAINID = 0x46 + SELFBALANCE = 0x47 ) // 0x50 range - 'storage' and execution. @@ -271,12 +273,14 @@ var opCodeToString = map[OpCode]string{ EXTCODEHASH: "EXTCODEHASH", // 0x40 range - block operations. - BLOCKHASH: "BLOCKHASH", - COINBASE: "COINBASE", - TIMESTAMP: "TIMESTAMP", - NUMBER: "NUMBER", - DIFFICULTY: "DIFFICULTY", - GASLIMIT: "GASLIMIT", + BLOCKHASH: "BLOCKHASH", + COINBASE: "COINBASE", + TIMESTAMP: "TIMESTAMP", + NUMBER: "NUMBER", + DIFFICULTY: "DIFFICULTY", + GASLIMIT: "GASLIMIT", + CHAINID: "CHAINID", + SELFBALANCE: "SELFBALANCE", // 0x50 range - 'storage' and execution. POP: "POP", @@ -428,6 +432,7 @@ var stringToOp = map[string]OpCode{ "CALLDATALOAD": CALLDATALOAD, "CALLDATASIZE": CALLDATASIZE, "CALLDATACOPY": CALLDATACOPY, + "CHAINID": CHAINID, "DELEGATECALL": DELEGATECALL, "STATICCALL": STATICCALL, "CODESIZE": CODESIZE, @@ -444,6 +449,7 @@ var stringToOp = map[string]OpCode{ "NUMBER": NUMBER, "DIFFICULTY": DIFFICULTY, "GASLIMIT": GASLIMIT, + "SELFBALANCE": SELFBALANCE, "POP": POP, "MLOAD": MLOAD, "MSTORE": MSTORE, diff --git a/vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go b/vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go index a4b1cfcd8..10c12901a 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go +++ b/vendor/github.com/ethereum/go-ethereum/core/vm/stack_table.go @@ -17,28 +17,26 @@ package vm import ( - "fmt" - "github.com/ethereum/go-ethereum/params" ) -func makeStackFunc(pop, push int) stackValidationFunc { - return func(stack *Stack) error { - if err := stack.require(pop); err != nil { - return err - } - - if stack.len()+push-pop > int(params.StackLimit) { - return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit) - } - return nil - } +func minSwapStack(n int) int { + return minStack(n, n) +} +func maxSwapStack(n int) int { + return maxStack(n, n) } -func makeDupStackFunc(n int) stackValidationFunc { - return makeStackFunc(n, n+1) +func minDupStack(n int) int { + return minStack(n, n+1) +} +func maxDupStack(n int) int { + return maxStack(n, n+1) } -func makeSwapStackFunc(n int) stackValidationFunc { - return makeStackFunc(n, n) +func maxStack(pop, push int) int { + return int(params.StackLimit) + pop - push +} +func minStack(pops, push int) int { + return pops } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go new file mode 100644 index 000000000..5da50cab6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b.go @@ -0,0 +1,319 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xb. +// +// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf +// and for BLAKE2Xb see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). +// If you need a secret-key MAC (message authentication code), use the New512 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 64 bytes. It +// can produce hash values between 0 and 4 GiB. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var ( + errKeySize = errors.New("blake2b: invalid key size") + errHashSize = errors.New("blake2b: invalid hash size") +) + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. +// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. +// The hash size can be a value between 1 and 64 but it is highly recommended to use +// values equal or greater than: +// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). +// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. +func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } + +// F is a compression function for BLAKE2b. It takes as an argument the state +// vector `h`, message block vector `m`, offset counter `t`, final block indicator +// flag `f`, and number of rounds `rounds`. The state vector provided as the first +// parameter is modified by the function. +func F(h *[8]uint64, m [16]uint64, c [2]uint64, final bool, rounds uint32) { + var flag uint64 + if final { + flag = 0xFFFFFFFFFFFFFFFF + } + f(h, &m, c[0], c[1], flag, uint64(rounds)) +} + +func newDigest(hashSize int, key []byte) (*digest, error) { + if hashSize < 1 || hashSize > Size { + return nil, errHashSize + } + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + f(h, &m, c0, c1, flag, 12) + } + c[0], c[1] = c0, c1 +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint64(hash[8*i:], v) + } +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 000000000..0d52b1869 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +//go:noescape +func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +//go:noescape +func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + switch { + case useAVX2: + fAVX2(h, m, c0, c1, flag, rounds) + case useAVX: + fAVX(h, m, c0, c1, flag, rounds) + case useSSE4: + fSSE4(h, m, c0, c1, flag, rounds) + default: + fGeneric(h, m, c0, c1, flag, rounds) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 000000000..4998af37d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,717 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 + +#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 +#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 +#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e +#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 +#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 + +#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ + VPADDQ m0, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m1, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y1_Y1; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y3_Y3; \ + VPADDQ m2, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m3, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y3_Y3; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y1_Y1 + +#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E +#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 +#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E +#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 +#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E + +#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n +#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n +#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n +#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n +#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n + +#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 +#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 +#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 +#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 +#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 + +#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 + +#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 +#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 + +// load msg: Y12 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y12, Y12 + +// load msg: Y13 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ + VMOVQ_SI_X13(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X13(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y13, Y13 + +// load msg: Y14 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ + VMOVQ_SI_X14(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X14(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y14, Y14 + +// load msg: Y15 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ + VMOVQ_SI_X15(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X15(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X11(6*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ + LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) + +#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ + LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ + LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ + VMOVQ_SI_X11(11*8); \ + VPSHUFD $0x4E, 0*8(SI), X14; \ + VPINSRQ_1_SI_X11(5*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) + +#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ + VMOVQ_SI_X11(5*8); \ + VMOVDQU 11*8(SI), X12; \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + VMOVQ_SI_X13(8*8); \ + VMOVQ_SI_X11(2*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X11(13*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) + +#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ + LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ + LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ + LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ + VMOVQ_SI_X15(6*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X15(10*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ + LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X13(7*8); \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) + +#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ + LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) + +#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ + LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ + LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ + VMOVQ_SI_X14_0; \ + VPSHUFD $0x4E, 8*8(SI), X11; \ + VPINSRQ_1_SI_X14(6*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) + +#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ + LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ + LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ + LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ + VMOVQ_SI_X15_0; \ + VMOVQ_SI_X11(6*8); \ + VPINSRQ_1_SI_X15(4*8); \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ + VMOVQ_SI_X12(6*8); \ + VMOVQ_SI_X11(11*8); \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ + VMOVQ_SI_X11(1*8); \ + VMOVDQU 12*8(SI), X14; \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + VMOVQ_SI_X15(2*8); \ + VMOVDQU 4*8(SI), X11; \ + VPINSRQ_1_SI_X15(7*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ + LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ + VMOVQ_SI_X13(2*8); \ + VPSHUFD $0x4E, 5*8(SI), X11; \ + VPINSRQ_1_SI_X13(4*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ + VMOVQ_SI_X15(11*8); \ + VMOVQ_SI_X11(12*8); \ + VPINSRQ_1_SI_X15(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y15, Y15 + +// func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fAVX2(SB), 4, $64-48 // frame size = 32 + 32 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, DX + MOVQ SP, R10 + ADDQ $31, R10 + ANDQ $~31, R10 + MOVQ R10, SP + + MOVQ CX, 16(SP) + XORQ CX, CX + MOVQ CX, 24(SP) + + VMOVDQU ·AVX2_c40<>(SB), Y4 + VMOVDQU ·AVX2_c48<>(SB), Y5 + + VMOVDQU 0(AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>(SB), Y6 + VMOVDQU ·AVX2_iv1<>(SB), Y7 + + MOVQ R8, 0(SP) + MOVQ R9, 8(SP) + + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR 0(SP), Y7, Y3 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + JMP loop + +done: + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + + VMOVDQU Y8, 0(AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + + MOVQ DX, SP + RET + +#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA +#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB +#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF +#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD +#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE + +#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF +#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF + +#define SHUFFLE_AVX() \ + VMOVDQA X6, X13; \ + VMOVDQA X2, X14; \ + VMOVDQA X4, X6; \ + VPUNPCKLQDQ_X13_X13_X15; \ + VMOVDQA X5, X4; \ + VMOVDQA X6, X5; \ + VPUNPCKHQDQ_X15_X7_X6; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X13_X7; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VPUNPCKHQDQ_X15_X2_X2; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X3_X3; \ + +#define SHUFFLE_AVX_INV() \ + VMOVDQA X2, X13; \ + VMOVDQA X4, X14; \ + VPUNPCKLQDQ_X2_X2_X15; \ + VMOVDQA X5, X4; \ + VPUNPCKHQDQ_X15_X3_X2; \ + VMOVDQA X14, X5; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VMOVDQA X6, X14; \ + VPUNPCKHQDQ_X15_X13_X3; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X6_X6; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X7_X7; \ + +#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + VPADDQ m0, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m1, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFD $-79, v6, v6; \ + VPSHUFD $-79, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPSHUFB c40, v2, v2; \ + VPSHUFB c40, v3, v3; \ + VPADDQ m2, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m3, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFB c48, v6, v6; \ + VPSHUFB c48, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPADDQ v2, v2, t0; \ + VPSRLQ $63, v2, v2; \ + VPXOR t0, v2, v2; \ + VPADDQ v3, v3, t0; \ + VPSRLQ $63, v3, v3; \ + VPXOR t0, v3, v3 + +// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X13(i2*8); \ + VMOVQ_SI_X14(i4*8); \ + VMOVQ_SI_X15(i6*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X13(i3*8); \ + VPINSRQ_1_SI_X14(i5*8); \ + VPINSRQ_1_SI_X15(i7*8) + +// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(1*8); \ + VMOVQ_SI_X15(5*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X13(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(7*8) + +// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ + VPSHUFD $0x4E, 0*8(SI), X12; \ + VMOVQ_SI_X13(11*8); \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(7*8); \ + VPINSRQ_1_SI_X13(5*8); \ + VPINSRQ_1_SI_X14(2*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ + VMOVDQU 11*8(SI), X12; \ + VMOVQ_SI_X13(5*8); \ + VMOVQ_SI_X14(8*8); \ + VMOVQ_SI_X15(2*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14_0; \ + VPINSRQ_1_SI_X15(13*8) + +// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(6*8); \ + VMOVQ_SI_X15_0; \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ + VMOVQ_SI_X12(9*8); \ + VMOVQ_SI_X13(2*8); \ + VMOVQ_SI_X14_0; \ + VMOVQ_SI_X15(4*8); \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VPINSRQ_1_SI_X15(15*8) + +// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(11*8); \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X13(8*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ + MOVQ 0*8(SI), X12; \ + VPSHUFD $0x4E, 8*8(SI), X13; \ + MOVQ 7*8(SI), X14; \ + MOVQ 2*8(SI), X15; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(11*8) + +// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ + MOVQ 6*8(SI), X12; \ + MOVQ 11*8(SI), X13; \ + MOVQ 15*8(SI), X14; \ + MOVQ 3*8(SI), X15; \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X14(9*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ + MOVQ 5*8(SI), X12; \ + MOVQ 8*8(SI), X13; \ + MOVQ 0*8(SI), X14; \ + MOVQ 6*8(SI), X15; \ + VPINSRQ_1_SI_X12(15*8); \ + VPINSRQ_1_SI_X13(2*8); \ + VPINSRQ_1_SI_X14(4*8); \ + VPINSRQ_1_SI_X15(10*8) + +// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ + VMOVDQU 12*8(SI), X12; \ + MOVQ 1*8(SI), X13; \ + MOVQ 2*8(SI), X14; \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VMOVDQU 4*8(SI), X15 + +// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ + MOVQ 15*8(SI), X12; \ + MOVQ 3*8(SI), X13; \ + MOVQ 11*8(SI), X14; \ + MOVQ 12*8(SI), X15; \ + VPINSRQ_1_SI_X12(9*8); \ + VPINSRQ_1_SI_X13(13*8); \ + VPINSRQ_1_SI_X14(14*8); \ + VPINSRQ_1_SI_X15_0 + +// func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fAVX(SB), 4, $24-48 // frame size = 8 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, BP + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + MOVQ R10, SP + + VMOVDQU ·AVX_c40<>(SB), X0 + VMOVDQU ·AVX_c48<>(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + + VMOVDQU ·AVX_iv3<>(SB), X0 + VMOVDQA X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU 0(AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + + VMOVQ_R8_X15 + VPINSRQ_1_R9_X15 + + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>(SB), X4 + VMOVDQU ·AVX_iv1<>(SB), X5 + VMOVDQU ·AVX_iv2<>(SB), X6 + + VPXOR X15, X6, X6 + VMOVDQA 0(SP), X7 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + SUBQ $1, BX; JCS done + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + JMP loop + +done: + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + + VMOVDQU X10, 0(AX) + VMOVDQU X11, 16(AX) + VZEROUPPER + + MOVQ BP, SP + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go new file mode 100644 index 000000000..4dbe90da8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.go @@ -0,0 +1,24 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7,amd64,!gccgo,!appengine + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + if useSSE4 { + fSSE4(h, m, c0, c1, flag, rounds) + } else { + fGeneric(h, m, c0, c1, flag, rounds) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 000000000..ce4b56d10 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,253 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + PADDQ m0, v0; \ + PADDQ m1, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v6, v6; \ + PSHUFD $0xB1, v7, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + PSHUFB c40, v2; \ + PSHUFB c40, v3; \ + PADDQ m2, v0; \ + PADDQ m3, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFB c48, v6; \ + PSHUFB c48, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + MOVOU v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVOU v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG(m0, m1, m2, m3, i0, i1, i2, i3, i4, i5, i6, i7) \ + MOVQ i0*8(SI), m0; \ + PINSRQ $1, i1*8(SI), m0; \ + MOVQ i2*8(SI), m1; \ + PINSRQ $1, i3*8(SI), m1; \ + MOVQ i4*8(SI), m2; \ + PINSRQ $1, i5*8(SI), m2; \ + MOVQ i6*8(SI), m3; \ + PINSRQ $1, i7*8(SI), m3 + +// func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) +TEXT ·fSSE4(SB), 4, $24-48 // frame size = 8 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ m+8(FP), SI + MOVQ c0+16(FP), R8 + MOVQ c1+24(FP), R9 + MOVQ flag+32(FP), CX + MOVQ rounds+40(FP), BX + + MOVQ SP, BP + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + MOVQ R10, SP + + MOVOU ·iv3<>(SB), X0 + MOVO X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) + + MOVOU ·c40<>(SB), X13 + MOVOU ·c48<>(SB), X14 + + MOVOU 0(AX), X12 + MOVOU 16(AX), X15 + + MOVQ R8, X8 + PINSRQ $1, R9, X8 + + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>(SB), X4 + MOVOU ·iv1<>(SB), X5 + MOVOU ·iv2<>(SB), X6 + + PXOR X8, X6 + MOVO 0(SP), X7 + +loop: + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 0, 2, 4, 6, 1, 3, 5, 7) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 8, 10, 12, 14, 9, 11, 13, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 14, 4, 9, 13, 10, 8, 15, 6) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 1, 0, 11, 5, 12, 2, 7, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + SUBQ $1, BX; JCS done + LOAD_MSG(X8, X9, X10, X11, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + JMP loop + +done: + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + + MOVOU X12, 0(AX) + MOVOU X15, 16(AX) + + MOVQ BP, SP + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go new file mode 100644 index 000000000..ab7334280 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_f_fuzz.go @@ -0,0 +1,57 @@ +// +build gofuzz + +package blake2b + +import ( + "encoding/binary" +) + +func Fuzz(data []byte) int { + // Make sure the data confirms to the input model + if len(data) != 211 { + return 0 + } + // Parse everything and call all the implementations + var ( + rounds = binary.BigEndian.Uint16(data[0:2]) + + h [8]uint64 + m [16]uint64 + t [2]uint64 + f uint64 + ) + for i := 0; i < 8; i++ { + offset := 2 + i*8 + h[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) + } + for i := 0; i < 16; i++ { + offset := 66 + i*8 + m[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) + } + t[0] = binary.LittleEndian.Uint64(data[194:202]) + t[1] = binary.LittleEndian.Uint64(data[202:210]) + + if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1 + f = 0xFFFFFFFFFFFFFFFF + } + // Run the blake2b compression on all instruction sets and cross reference + want := h + fGeneric(&want, &m, t[0], t[1], f, uint64(rounds)) + + have := h + fSSE4(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("SSE4 mismatches generic algo") + } + have = h + fAVX(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("AVX mismatches generic algo") + } + have = h + fAVX2(&have, &m, t[0], t[1], f, uint64(rounds)) + if have != want { + panic("AVX2 mismatches generic algo") + } + return 1 +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go new file mode 100644 index 000000000..35c40cc92 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,180 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "math/bits" +) + +// the precomputed values for BLAKE2b +// there are 10 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [10][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + fGeneric(h, &m, c0, c1, flag, 12) + } + c[0], c[1] = c0, c1 +} + +func fGeneric(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for i := 0; i < int(rounds); i++ { + s := &(precomputed[i%10]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -32) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -24) + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -32) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -24) + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -32) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -24) + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -32) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -24) + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -16) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -63) + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -16) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -63) + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -16) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -63) + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -16) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -63) + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -32) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -24) + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -32) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -24) + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -32) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -24) + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -32) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -24) + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -16) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -63) + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -16) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -63) + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -16) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -63) + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -16) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -63) + } + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go new file mode 100644 index 000000000..9d0ade473 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine gccgo + +package blake2b + +func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { + fGeneric(h, m, c0, c1, flag, rounds) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go new file mode 100644 index 000000000..52c414db0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/blake2x.go @@ -0,0 +1,177 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = (1 << 32) - 1 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 64 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 256GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint32, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^32-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2b: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint32 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2b: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length + x.cfg[17] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[1] ^= uint64(x.length) << 32 + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go new file mode 100644 index 000000000..efd689af4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/blake2b/register.go @@ -0,0 +1,32 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package blake2b + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + newHash384 := func() hash.Hash { + h, _ := New384(nil) + return h + } + + newHash512 := func() hash.Hash { + h, _ := New512(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) + crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) + crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go index c6ea2d07e..38822a76b 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/bn256.go @@ -100,6 +100,10 @@ func (e *G1) Marshal() []byte { // Each value is a 256-bit number. const numBytes = 256 / 8 + if e.p == nil { + e.p = &curvePoint{} + } + e.p.MakeAffine() ret := make([]byte, numBytes*2) if e.p.IsInfinity() { @@ -382,6 +386,11 @@ func (e *GT) Marshal() []byte { // Each value is a 256-bit number. const numBytes = 256 / 8 + if e.p == nil { + e.p = &gfP12{} + e.p.SetOne() + } + ret := make([]byte, numBytes*12) temp := &gfP{} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go index 5122aae64..f7d2c7c00 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/constants.go @@ -13,10 +13,13 @@ func bigFromBase10(s string) *big.Int { return n } -// u is the BN parameter that determines the prime: 1868033³. +// u is the BN parameter. var u = bigFromBase10("4965661367192848881") // Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. +// Needs to be highly 2-adic for efficient SNARK key and proof generation. +// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081. +// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters. var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") // P is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go index 83d61b781..a42734911 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/bn256/cloudflare/gfp6.go @@ -5,7 +5,7 @@ package bn256 // http://eprint.iacr.org/2006/471.pdf. // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ -// and ξ=i+3. +// and ξ=i+9. type gfP6 struct { x, y, z gfP2 // value is xτ² + yτ + z } diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go index 4567fafc7..2869b4c19 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go @@ -34,6 +34,15 @@ import ( "golang.org/x/crypto/sha3" ) +//SignatureLength indicates the byte length required to carry a signature with recovery id. +const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id + +// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id. +const RecoveryIDOffset = 64 + +// DigestLength sets the signature digest exact length +const DigestLength = 32 + var ( secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2)) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go index 340bfc221..1fe84509e 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build !nacl,!js,!nocgo +// +build !nacl,!js,cgo package crypto @@ -47,24 +47,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // // This function is susceptible to chosen plaintext attacks that can leak // information about the private key that is used for signing. Callers must -// be aware that the given hash cannot be chosen by an adversery. Common +// be aware that the given digest cannot be chosen by an adversery. Common // solution is to hash any input before calculating the signature. // // The produced signature is in the [R || S || V] format where V is 0 or 1. -func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - if len(hash) != 32 { - return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) +func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { + if len(digestHash) != DigestLength { + return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash)) } seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8) defer zeroBytes(seckey) - return secp256k1.Sign(hash, seckey) + return secp256k1.Sign(digestHash, seckey) } -// VerifySignature checks that the given public key created signature over hash. +// VerifySignature checks that the given public key created signature over digest. // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. // The signature should have the 64 byte [R || S] format. -func VerifySignature(pubkey, hash, signature []byte) bool { - return secp256k1.VerifySignature(pubkey, hash, signature) +func VerifySignature(pubkey, digestHash, signature []byte) bool { + return secp256k1.VerifySignature(pubkey, digestHash, signature) } // DecompressPubkey parses a public key in the 33-byte compressed format. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go index e8fa18ed4..067d32e13 100644 --- a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build nacl js nocgo +// +build nacl js !cgo package crypto @@ -41,7 +41,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) { // SigToPub returns the public key that created the given signature. func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // Convert to btcec input format with 'recovery id' v at the beginning. - btcsig := make([]byte, 65) + btcsig := make([]byte, SignatureLength) btcsig[0] = sig[64] + 27 copy(btcsig[1:], sig) diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api.go b/vendor/github.com/ethereum/go-ethereum/eth/api.go index 816b9cd33..f8c51c09b 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/api.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/api.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" @@ -70,7 +69,7 @@ func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 { // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. func (api *PublicEthereumAPI) ChainId() hexutil.Uint64 { chainID := new(big.Int) - if config := api.e.chainConfig; config.IsEIP155(api.e.blockchain.CurrentBlock().Number()) { + if config := api.e.blockchain.Config(); config.IsEIP155(api.e.blockchain.CurrentBlock().Number()) { chainID = config.ChainID } return (hexutil.Uint64)(chainID.Uint64()) @@ -169,6 +168,11 @@ func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI { // ExportChain exports the current blockchain into a local file. func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) { + if _, err := os.Stat(file); err == nil { + // File already exists. Allowing overwrite could be a DoS vecotor, + // since the 'file' may point to arbitrary paths on the drive + return false, errors.New("location would overwrite an existing file") + } // Make sure we can create the file to export into out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) if err != nil { @@ -267,7 +271,7 @@ func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error // both the pending block as well as the pending state from // the miner and operate on those _, stateDb := api.eth.miner.Pending() - return stateDb.RawDump(), nil + return stateDb.RawDump(false, false, true), nil } var block *types.Block if blockNr == rpc.LatestBlockNumber { @@ -282,20 +286,19 @@ func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error if err != nil { return state.Dump{}, err } - return stateDb.RawDump(), nil + return stateDb.RawDump(false, false, true), nil } // PrivateDebugAPI is the collection of Ethereum full node APIs exposed over // the private debugging endpoint. type PrivateDebugAPI struct { - config *params.ChainConfig - eth *Ethereum + eth *Ethereum } // NewPrivateDebugAPI creates a new API definition for the full node-related // private debug methods of the Ethereum service. -func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI { - return &PrivateDebugAPI{config: config, eth: eth} +func NewPrivateDebugAPI(eth *Ethereum) *PrivateDebugAPI { + return &PrivateDebugAPI{eth: eth} } // Preimage is a debug API function that returns the preimage for a sha3 hash, if known. @@ -336,6 +339,72 @@ func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, return results, nil } +// AccountRangeResult returns a mapping from the hash of an account addresses +// to its preimage. It will return the JSON null if no preimage is found. +// Since a query can return a limited amount of results, a "next" field is +// also present for paging. +type AccountRangeResult struct { + Accounts map[common.Hash]*common.Address `json:"accounts"` + Next common.Hash `json:"next"` +} + +func accountRange(st state.Trie, start *common.Hash, maxResults int) (AccountRangeResult, error) { + if start == nil { + start = &common.Hash{0} + } + it := trie.NewIterator(st.NodeIterator(start.Bytes())) + result := AccountRangeResult{Accounts: make(map[common.Hash]*common.Address), Next: common.Hash{}} + + if maxResults > AccountRangeMaxResults { + maxResults = AccountRangeMaxResults + } + + for i := 0; i < maxResults && it.Next(); i++ { + if preimage := st.GetKey(it.Key); preimage != nil { + addr := &common.Address{} + addr.SetBytes(preimage) + result.Accounts[common.BytesToHash(it.Key)] = addr + } else { + result.Accounts[common.BytesToHash(it.Key)] = nil + } + } + + if it.Next() { + result.Next = common.BytesToHash(it.Key) + } + + return result, nil +} + +// AccountRangeMaxResults is the maximum number of results to be returned per call +const AccountRangeMaxResults = 256 + +// AccountRange enumerates all accounts in the latest state +func (api *PrivateDebugAPI) AccountRange(ctx context.Context, start *common.Hash, maxResults int) (AccountRangeResult, error) { + var statedb *state.StateDB + var err error + block := api.eth.blockchain.CurrentBlock() + + if len(block.Transactions()) == 0 { + statedb, err = api.computeStateDB(block, defaultTraceReexec) + if err != nil { + return AccountRangeResult{}, err + } + } else { + _, _, statedb, err = api.computeTxEnv(block.Hash(), len(block.Transactions())-1, 0) + if err != nil { + return AccountRangeResult{}, err + } + } + + trie, err := statedb.Database().OpenTrie(block.Header().Root) + if err != nil { + return AccountRangeResult{}, err + } + + return accountRange(trie, start, maxResults) +} + // StorageRangeResult is the result of a debug_storageRangeAt API call. type StorageRangeResult struct { Storage storageMap `json:"storage"` @@ -446,11 +515,11 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc } triedb := api.eth.BlockChain().StateCache().TrieDB() - oldTrie, err := trie.NewSecure(startBlock.Root(), triedb, 0) + oldTrie, err := trie.NewSecure(startBlock.Root(), triedb) if err != nil { return nil, err } - newTrie, err := trie.NewSecure(endBlock.Root(), triedb, 0) + newTrie, err := trie.NewSecure(endBlock.Root(), triedb) if err != nil { return nil, err } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go index 3efc09cc1..69904a70f 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/api_backend.go @@ -18,6 +18,7 @@ package eth import ( "context" + "errors" "math/big" "github.com/ethereum/go-ethereum/accounts" @@ -25,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -38,13 +40,14 @@ import ( // EthAPIBackend implements ethapi.Backend for full nodes type EthAPIBackend struct { - eth *Ethereum - gpo *gasprice.Oracle + extRPCEnabled bool + eth *Ethereum + gpo *gasprice.Oracle } // ChainConfig returns the active chain configuration. func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { - return b.eth.chainConfig + return b.eth.blockchain.Config() } func (b *EthAPIBackend) CurrentBlock() *types.Block { @@ -56,55 +59,58 @@ func (b *EthAPIBackend) SetHead(number uint64) { b.eth.blockchain.SetHead(number) } -func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { +func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { // Pending block is only known by the miner - if blockNr == rpc.PendingBlockNumber { + if number == rpc.PendingBlockNumber { block := b.eth.miner.PendingBlock() return block.Header(), nil } // Otherwise resolve and return the block - if blockNr == rpc.LatestBlockNumber { + if number == rpc.LatestBlockNumber { return b.eth.blockchain.CurrentBlock().Header(), nil } - return b.eth.blockchain.GetHeaderByNumber(uint64(blockNr)), nil + return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil } func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { return b.eth.blockchain.GetHeaderByHash(hash), nil } -func (b *EthAPIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) { +func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { // Pending block is only known by the miner - if blockNr == rpc.PendingBlockNumber { + if number == rpc.PendingBlockNumber { block := b.eth.miner.PendingBlock() return block, nil } // Otherwise resolve and return the block - if blockNr == rpc.LatestBlockNumber { + if number == rpc.LatestBlockNumber { return b.eth.blockchain.CurrentBlock(), nil } - return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil + return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil } -func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return b.eth.blockchain.GetBlockByHash(hash), nil +} + +func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { // Pending state is only known by the miner - if blockNr == rpc.PendingBlockNumber { + if number == rpc.PendingBlockNumber { block, state := b.eth.miner.Pending() return state, block.Header(), nil } // Otherwise resolve the block number and return its state - header, err := b.HeaderByNumber(ctx, blockNr) - if header == nil || err != nil { + header, err := b.HeaderByNumber(ctx, number) + if err != nil { return nil, nil, err } + if header == nil { + return nil, nil, errors.New("header not found") + } stateDb, err := b.eth.BlockChain().StateAt(header.Root) return stateDb, header, err } -func (b *EthAPIBackend) GetBlock(ctx context.Context, hash common.Hash) (*types.Block, error) { - return b.eth.blockchain.GetBlockByHash(hash), nil -} - func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { return b.eth.blockchain.GetReceiptsByHash(hash), nil } @@ -130,7 +136,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *sta vmError := func() error { return nil } context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil) - return vm.NewEVM(context, state, b.eth.chainConfig, *b.eth.blockchain.GetVMConfig()), vmError, nil + return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil } func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { @@ -173,8 +179,13 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction return b.eth.txPool.Get(hash) } +func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { + tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash) + return tx, blockHash, blockNumber, index, nil +} + func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { - return b.eth.txPool.State().GetNonce(addr), nil + return b.eth.txPool.Nonce(addr), nil } func (b *EthAPIBackend) Stats() (pending int, queued int) { @@ -213,6 +224,10 @@ func (b *EthAPIBackend) AccountManager() *accounts.Manager { return b.eth.AccountManager() } +func (b *EthAPIBackend) ExtRPCEnabled() bool { + return b.extRPCEnabled +} + func (b *EthAPIBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/api_tracer.go b/vendor/github.com/ethereum/go-ethereum/eth/api_tracer.go index a3a0b4e1e..ce211cbd9 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/api_tracer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/api_tracer.go @@ -201,7 +201,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl // Fetch and execute the next block trace tasks for task := range tasks { - signer := types.MakeSigner(api.config, task.block.Number()) + signer := types.MakeSigner(api.eth.blockchain.Config(), task.block.Number()) // Trace all the transactions contained within for i, tx := range task.block.Transactions() { @@ -295,7 +295,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl break } // Finalize the state so any modifications are written to the trie - root, err := statedb.Commit(true) + root, err := statedb.Commit(api.eth.blockchain.Config().IsEIP158(block.Number())) if err != nil { failed = err break @@ -460,7 +460,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, } // Execute all the transaction contained within the block concurrently var ( - signer = types.MakeSigner(api.config, block.Number()) + signer = types.MakeSigner(api.eth.blockchain.Config(), block.Number()) txs = block.Transactions() results = make([]*txTraceResult, len(txs)) @@ -501,7 +501,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, msg, _ := tx.AsMessage(signer) vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) - vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{}) + vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{}) if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { failed = err break @@ -526,13 +526,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) { // If we're tracing a single transaction, make sure it's present if config != nil && config.TxHash != (common.Hash{}) { - var exists bool - for _, tx := range block.Transactions() { - if exists = (tx.Hash() == config.TxHash); exists { - break - } - } - if !exists { + if !containsTx(block, config.TxHash) { return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash) } } @@ -567,7 +561,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block // Execute transaction, either tracing all or just the requested one var ( - signer = types.MakeSigner(api.config, block.Number()) + signer = types.MakeSigner(api.eth.blockchain.Config(), block.Number()) dumps []string ) for i, tx := range block.Transactions() { @@ -578,6 +572,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block vmConf vm.Config dump *os.File + writer *bufio.Writer err error ) // If the transaction needs tracing, swap out the configs @@ -592,16 +587,19 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block dumps = append(dumps, dump.Name()) // Swap out the noop logger to the standard tracer + writer = bufio.NewWriter(dump) vmConf = vm.Config{ Debug: true, - Tracer: vm.NewJSONLogger(&logConfig, bufio.NewWriter(dump)), + Tracer: vm.NewJSONLogger(&logConfig, writer), EnablePreimageRecording: true, } } // Execute the transaction and flush any traces to disk - vmenv := vm.NewEVM(vmctx, statedb, api.config, vmConf) + vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vmConf) _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) - + if writer != nil { + writer.Flush() + } if dump != nil { dump.Close() log.Info("Wrote standard trace", "file", dump.Name()) @@ -621,6 +619,17 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block return dumps, nil } +// containsTx reports whether the transaction with a certain hash +// is contained within the specified block. +func containsTx(block *types.Block, hash common.Hash) bool { + for _, tx := range block.Transactions() { + if tx.Hash() == hash { + return true + } + } + return false +} + // computeStateDB retrieves the state database associated with a certain block. // If no state is locally available for the given block, a number of blocks are // attempted to be reexecuted to generate the desired state. @@ -747,7 +756,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v tracer = vm.NewStructLogger(config.LogConfig) } // Run the transaction with tracing enabled. - vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{Debug: true, Tracer: tracer}) + vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer}) ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) if err != nil { @@ -786,8 +795,13 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree if err != nil { return nil, vm.Context{}, nil, err } + + if txIndex == 0 && len(block.Transactions()) == 0 { + return nil, vm.Context{}, statedb, nil + } + // Recompute transactions up to the target index. - signer := types.MakeSigner(api.config, block.Number()) + signer := types.MakeSigner(api.eth.blockchain.Config(), block.Number()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset @@ -797,7 +811,7 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree return msg, context, statedb, nil } // Not yet the searched for transaction, execute on top of the current state - vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{}) + vmenv := vm.NewEVM(context, statedb, api.eth.blockchain.Config(), vm.Config{}) if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/backend.go b/vendor/github.com/ethereum/go-ethereum/eth/backend.go index 2a9d56c5c..83e05e96a 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/backend.go @@ -26,6 +26,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" @@ -46,6 +47,7 @@ import ( "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -54,17 +56,18 @@ import ( type LesServer interface { Start(srvr *p2p.Server) Stop() + APIs() []rpc.API Protocols() []p2p.Protocol SetBloomBitsIndexer(bbIndexer *core.ChainIndexer) + SetContractBackend(bind.ContractBackend) } // Ethereum implements the Ethereum full node service. type Ethereum struct { - config *Config - chainConfig *params.ChainConfig + config *Config // Channel for shutting down the service - shutdownChan chan bool // Channel for shutting down the Ethereum + shutdownChan chan bool // Handlers txPool *core.TxPool @@ -99,6 +102,14 @@ func (s *Ethereum) AddLesServer(ls LesServer) { ls.SetBloomBitsIndexer(s.bloomIndexer) } +// SetClient sets a rpc client which connecting to our local node. +func (s *Ethereum) SetContractBackend(backend bind.ContractBackend) { + // Pass the rpc client to les server if it is enabled. + if s.lesServer != nil { + s.lesServer.SetContractBackend(backend) + } +} + // New creates a new Ethereum object (including the // initialisation of the common Ethereum object) func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { @@ -109,16 +120,22 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if !config.SyncMode.IsValid() { return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) } - if config.MinerGasPrice == nil || config.MinerGasPrice.Cmp(common.Big0) <= 0 { - log.Warn("Sanitizing invalid miner gas price", "provided", config.MinerGasPrice, "updated", DefaultConfig.MinerGasPrice) - config.MinerGasPrice = new(big.Int).Set(DefaultConfig.MinerGasPrice) + if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { + log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", DefaultConfig.Miner.GasPrice) + config.Miner.GasPrice = new(big.Int).Set(DefaultConfig.Miner.GasPrice) } + if config.NoPruning && config.TrieDirtyCache > 0 { + config.TrieCleanCache += config.TrieDirtyCache + config.TrieDirtyCache = 0 + } + log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) + // Assemble the Ethereum object - chainDb, err := CreateDB(ctx, config, "chaindata") + chainDb, err := ctx.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/") if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.ConstantinopleOverride) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideIstanbul) if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } @@ -127,28 +144,31 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { eth := &Ethereum{ config: config, chainDb: chainDb, - chainConfig: chainConfig, eventMux: ctx.EventMux, accountManager: ctx.AccountManager, - engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.MinerNotify, config.MinerNoverify, chainDb), + engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb), shutdownChan: make(chan bool), networkID: config.NetworkId, - gasPrice: config.MinerGasPrice, - etherbase: config.Etherbase, + gasPrice: config.Miner.GasPrice, + etherbase: config.Miner.Etherbase, bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), } - log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId) + bcVersion := rawdb.ReadDatabaseVersion(chainDb) + var dbVer = "" + if bcVersion != nil { + dbVer = fmt.Sprintf("%d", *bcVersion) + } + log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId, "dbversion", dbVer) if !config.SkipBcVersionCheck { - bcVersion := rawdb.ReadDatabaseVersion(chainDb) if bcVersion != nil && *bcVersion > core.BlockChainVersion { return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) - } else if bcVersion != nil && *bcVersion < core.BlockChainVersion { - log.Warn("Upgrade blockchain database version", "from", *bcVersion, "to", core.BlockChainVersion) + } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { + log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) + rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) } - rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) } var ( vmConfig = vm.Config{ @@ -156,9 +176,15 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { EWASMInterpreter: config.EWASMInterpreter, EVMInterpreter: config.EVMInterpreter, } - cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout} + cacheConfig = &core.CacheConfig{ + TrieCleanLimit: config.TrieCleanCache, + TrieCleanNoPrefetch: config.NoPrefetch, + TrieDirtyLimit: config.TrieDirtyCache, + TrieDirtyDisabled: config.NoPruning, + TrieTimeLimit: config.TrieTimeout, + } ) - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve) + eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve) if err != nil { return nil, err } @@ -173,19 +199,24 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if config.TxPool.Journal != "" { config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) } - eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) + eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) - if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.Whitelist); err != nil { + // Permit the downloader to use the trie cache allowance during fast sync + cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + checkpoint := config.Checkpoint + if checkpoint == nil { + checkpoint = params.TrustedCheckpoints[genesisHash] + } + if eth.protocolManager, err = NewProtocolManager(chainConfig, checkpoint, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, cacheLimit, config.Whitelist); err != nil { return nil, err } + eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) + eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) - eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock) - eth.miner.SetExtra(makeExtraData(config.MinerExtraData)) - - eth.APIBackend = &EthAPIBackend{eth, nil} + eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil} gpoParams := config.GPO if gpoParams.Default == nil { - gpoParams.Default = config.MinerGasPrice + gpoParams.Default = config.Miner.GasPrice } eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) @@ -209,18 +240,6 @@ func makeExtraData(extra []byte) []byte { return extra } -// CreateDB creates the chain database. -func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) { - db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles) - if err != nil { - return nil, err - } - if db, ok := db.(*ethdb.LDBDatabase); ok { - db.Meter("eth/db/chaindata/") - } - return db, nil -} - // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { // If proof-of-authority is requested, set it up @@ -257,9 +276,18 @@ func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainCo func (s *Ethereum) APIs() []rpc.API { apis := ethapi.GetAPIs(s.APIBackend) + // Append any APIs exposed explicitly by the les server + if s.lesServer != nil { + apis = append(apis, s.lesServer.APIs()...) + } // Append any APIs exposed explicitly by the consensus engine apis = append(apis, s.engine.APIs(s.BlockChain())...) + // Append any APIs exposed explicitly by the les server + if s.lesServer != nil { + apis = append(apis, s.lesServer.APIs()...) + } + // Append all the local APIs and return return append(apis, []rpc.API{ { @@ -299,7 +327,7 @@ func (s *Ethereum) APIs() []rpc.API { }, { Namespace: "debug", Version: "1.0", - Service: NewPrivateDebugAPI(s.chainConfig, s), + Service: NewPrivateDebugAPI(s), }, { Namespace: "net", Version: "1.0", @@ -434,7 +462,7 @@ func (s *Ethereum) StartMining(threads int) error { log.Error("Etherbase account unavailable locally", "err", err) return fmt.Errorf("signer missing: %v", err) } - clique.Authorize(eb, wallet.SignHash) + clique.Authorize(eb, wallet.SignData) } // If mining is started, we can disable the transaction rejection mechanism // introduced to speed sync times. @@ -469,22 +497,31 @@ func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) IsListening() bool { return true } // Always listening -func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } +func (s *Ethereum) EthVersion() int { return int(ProtocolVersions[0]) } func (s *Ethereum) NetVersion() uint64 { return s.networkID } func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } +func (s *Ethereum) Synced() bool { return atomic.LoadUint32(&s.protocolManager.acceptTxs) == 1 } +func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning } // Protocols implements node.Service, returning all the currently configured // network protocols to start. func (s *Ethereum) Protocols() []p2p.Protocol { - if s.lesServer == nil { - return s.protocolManager.SubProtocols + protos := make([]p2p.Protocol, len(ProtocolVersions)) + for i, vsn := range ProtocolVersions { + protos[i] = s.protocolManager.makeProtocol(vsn) + protos[i].Attributes = []enr.Entry{s.currentEthEntry()} } - return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...) + if s.lesServer != nil { + protos = append(protos, s.lesServer.Protocols()...) + } + return protos } // Start implements node.Service, starting all internal goroutines needed by the // Ethereum protocol implementation. func (s *Ethereum) Start(srvr *p2p.Server) error { + s.startEthEntryUpdate(srvr.LocalNode()) + // Start the bloom bits servicing goroutines s.startBloomHandlers(params.BloomBitsBlocks) diff --git a/vendor/github.com/ethereum/go-ethereum/eth/bloombits.go b/vendor/github.com/ethereum/go-ethereum/eth/bloombits.go index c7bb56140..9a31997d6 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/bloombits.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/bloombits.go @@ -102,7 +102,7 @@ func NewBloomIndexer(db ethdb.Database, size, confirms uint64) *core.ChainIndexe db: db, size: size, } - table := ethdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) + table := rawdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) return core.NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits") } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/config.go b/vendor/github.com/ethereum/go-ethereum/eth/config.go index 3d5ba5813..5094a533b 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/config.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/config.go @@ -25,11 +25,11 @@ import ( "time" "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/eth/downloader" "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/params" ) @@ -43,17 +43,19 @@ var DefaultConfig = Config{ DatasetsInMem: 1, DatasetsOnDisk: 2, }, - NetworkId: 1, - LightPeers: 100, - DatabaseCache: 512, - TrieCleanCache: 256, - TrieDirtyCache: 256, - TrieTimeout: 60 * time.Minute, - MinerGasFloor: 8000000, - MinerGasCeil: 8000000, - MinerGasPrice: big.NewInt(params.GWei), - MinerRecommit: 3 * time.Second, - + NetworkId: 1, + LightPeers: 100, + UltraLightFraction: 75, + DatabaseCache: 512, + TrieCleanCache: 256, + TrieDirtyCache: 256, + TrieTimeout: 60 * time.Minute, + Miner: miner.Config{ + GasFloor: 8000000, + GasCeil: 8000000, + GasPrice: big.NewInt(params.GWei), + Recommit: 3 * time.Second, + }, TxPool: core.DefaultTxPoolConfig, GPO: gasprice.Config{ Blocks: 20, @@ -68,14 +70,21 @@ func init() { home = user.HomeDir } } - if runtime.GOOS == "windows" { - DefaultConfig.Ethash.DatasetDir = filepath.Join(home, "AppData", "Ethash") + if runtime.GOOS == "darwin" { + DefaultConfig.Ethash.DatasetDir = filepath.Join(home, "Library", "Ethash") + } else if runtime.GOOS == "windows" { + localappdata := os.Getenv("LOCALAPPDATA") + if localappdata != "" { + DefaultConfig.Ethash.DatasetDir = filepath.Join(localappdata, "Ethash") + } else { + DefaultConfig.Ethash.DatasetDir = filepath.Join(home, "AppData", "Local", "Ethash") + } } else { DefaultConfig.Ethash.DatasetDir = filepath.Join(home, ".ethash") } } -//go:generate gencodec -type Config -field-override configMarshaling -formats toml -out gen_config.go +//go:generate gencodec -type Config -formats toml -out gen_config.go type Config struct { // The genesis block, which is inserted if the database is empty. @@ -85,36 +94,36 @@ type Config struct { // Protocol options NetworkId uint64 // Network ID to use for selecting peers to connect to SyncMode downloader.SyncMode - NoPruning bool + + NoPruning bool // Whether to disable pruning and flush everything to disk + NoPrefetch bool // Whether to disable prefetching and only load state on demand // Whitelist of required block number -> hash values to accept Whitelist map[uint64]common.Hash `toml:"-"` // Light client options - LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests - LightPeers int `toml:",omitempty"` // Maximum number of LES client peers - OnlyAnnounce bool // Maximum number of LES client peers + LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests + LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers + LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers + LightPeers int `toml:",omitempty"` // Maximum number of LES client peers // Ultra Light client options - ULC *ULCConfig `toml:",omitempty"` + UltraLightServers []string `toml:",omitempty"` // List of trusted ultra light servers + UltraLightFraction int `toml:",omitempty"` // Percentage of trusted servers to accept an announcement + UltraLightOnlyAnnounce bool `toml:",omitempty"` // Whether to only announce headers, or also serve them // Database options SkipBcVersionCheck bool `toml:"-"` DatabaseHandles int `toml:"-"` DatabaseCache int - TrieCleanCache int - TrieDirtyCache int - TrieTimeout time.Duration + DatabaseFreezer string - // Mining-related options - Etherbase common.Address `toml:",omitempty"` - MinerNotify []string `toml:",omitempty"` - MinerExtraData []byte `toml:",omitempty"` - MinerGasFloor uint64 - MinerGasCeil uint64 - MinerGasPrice *big.Int - MinerRecommit time.Duration - MinerNoverify bool + TrieCleanCache int + TrieDirtyCache int + TrieTimeout time.Duration + + // Mining options + Miner miner.Config // Ethash options Ethash ethash.Config @@ -137,13 +146,15 @@ type Config struct { // Type of the EVM interpreter ("" for default) EVMInterpreter string - // Constantinople block override (TODO: remove after the fork) - ConstantinopleOverride *big.Int - // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap *big.Int `toml:",omitempty"` -} -type configMarshaling struct { - MinerExtraData hexutil.Bytes + // Checkpoint is a hardcoded checkpoint which can be nil. + Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` + + // CheckpointOracle is the configuration for checkpoint oracle. + CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` + + // Istanbul block override (TODO: remove after the fork) + OverrideIstanbul *big.Int } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go index 8457bc773..f6510bccd 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/downloader.go @@ -25,7 +25,7 @@ import ( "sync/atomic" "time" - ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" ) var ( @@ -45,20 +46,20 @@ var ( MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request MaxStateFetch = 384 // Amount of node state values to allow fetching per request - MaxForkAncestry = 3 * params.EpochDuration // Maximum chain reorganisation - rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests - rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests - rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value - ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion - ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts + rttMinEstimate = 2 * time.Second // Minimum round-trip time to target for download requests + rttMaxEstimate = 20 * time.Second // Maximum round-trip time to target for download requests + rttMinConfidence = 0.1 // Worse confidence factor in our estimated RTT value + ttlScaling = 3 // Constant scaling factor for RTT -> TTL conversion + ttlLimit = time.Minute // Maximum TTL allowance to prevent reaching crazy timeouts qosTuningPeers = 5 // Number of peers to tune based on (best peers) qosConfidenceCap = 10 // Number of peers above which not to modify RTT confidence qosTuningImpact = 0.25 // Impact that a new tuning target has on the previous value - maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) - maxHeadersProcess = 2048 // Number of header download results to import at once into the chain - maxResultsProcess = 2048 // Number of content download results to import at once into the chain + maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) + maxHeadersProcess = 2048 // Number of header download results to import at once into the chain + maxResultsProcess = 2048 // Number of content download results to import at once into the chain + maxForkAncestry uint64 = params.ImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection reorgProtHeaderDelay = 2 // Number of headers to delay delivering to cover mini reorgs @@ -82,21 +83,23 @@ var ( errPeersUnavailable = errors.New("no peers available or all tried for download") errInvalidAncestor = errors.New("retrieved ancestor is invalid") errInvalidChain = errors.New("retrieved hash chain is invalid") - errInvalidBlock = errors.New("retrieved block is invalid") errInvalidBody = errors.New("retrieved block body is invalid") errInvalidReceipt = errors.New("retrieved receipt is invalid") - errCancelBlockFetch = errors.New("block download canceled (requested)") - errCancelHeaderFetch = errors.New("block header download canceled (requested)") - errCancelBodyFetch = errors.New("block body download canceled (requested)") - errCancelReceiptFetch = errors.New("receipt download canceled (requested)") errCancelStateFetch = errors.New("state data download canceled (requested)") - errCancelHeaderProcessing = errors.New("header processing canceled (requested)") errCancelContentProcessing = errors.New("content processing canceled (requested)") + errCanceled = errors.New("syncing canceled (requested)") errNoSyncActive = errors.New("no sync active") errTooOld = errors.New("peer doesn't speak recent enough protocol version (need version >= 62)") ) type Downloader struct { + // WARNING: The `rttEstimate` and `rttConfidence` fields are accessed atomically. + // On 32 bit platforms, only 64-bit aligned fields can be atomic. The struct is + // guaranteed to be so aligned, so take advantage of that. For more information, + // see https://golang.org/pkg/sync/atomic/#pkg-note-BUG. + rttEstimate uint64 // Round trip time to target for download requests + rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops) + mode SyncMode // Synchronisation mode defining the strategy used (per sync cycle) mux *event.TypeMux // Event multiplexer to announce sync operation events @@ -104,10 +107,9 @@ type Downloader struct { genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT) queue *queue // Scheduler for selecting the hashes to download peers *peerSet // Set of active peers from which download can proceed - stateDB ethdb.Database - rttEstimate uint64 // Round trip time to target for download requests - rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops) + stateDB ethdb.Database // Database to state sync into (and deduplicate via) + stateBloom *trie.SyncBloom // Bloom filter for fast trie node existence checks // Statistics syncStatsChainOrigin uint64 // Origin block number where syncing started at @@ -126,6 +128,7 @@ type Downloader struct { synchronising int32 notified int32 committed int32 + ancientLimit uint64 // The maximum block number which can be regarded as ancient data. // Channels headerCh chan dataPack // [eth/62] Channel receiving inbound block headers @@ -205,17 +208,17 @@ type BlockChain interface { InsertChain(types.Blocks) (int, error) // InsertReceiptChain inserts a batch of receipts into the local chain. - InsertReceiptChain(types.Blocks, []types.Receipts) (int, error) + InsertReceiptChain(types.Blocks, []types.Receipts, uint64) (int, error) } // New creates a new downloader to fetch hashes and blocks from remote peers. -func New(mode SyncMode, checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { +func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { if lightchain == nil { lightchain = chain } dl := &Downloader{ - mode: mode, stateDB: stateDb, + stateBloom: stateBloom, mux: mux, checkpoint: checkpoint, queue: newQueue(), @@ -257,13 +260,15 @@ func (d *Downloader) Progress() ethereum.SyncProgress { defer d.syncStatsLock.RUnlock() current := uint64(0) - switch d.mode { - case FullSync: + switch { + case d.blockchain != nil && d.mode == FullSync: current = d.blockchain.CurrentBlock().NumberU64() - case FastSync: + case d.blockchain != nil && d.mode == FastSync: current = d.blockchain.CurrentFastBlock().NumberU64() - case LightSync: + case d.lightchain != nil: current = d.lightchain.CurrentHeader().Number.Uint64() + default: + log.Error("Unknown downloader chain/mode combo", "light", d.lightchain != nil, "full", d.blockchain != nil, "mode", d.mode) } return ethereum.SyncProgress{ StartingBlock: d.syncStatsChainOrigin, @@ -311,14 +316,6 @@ func (d *Downloader) UnregisterPeer(id string) error { } d.queue.Revoke(id) - // If this peer was the master peer, abort sync immediately - d.cancelLock.RLock() - master := id == d.cancelPeer - d.cancelLock.RUnlock() - - if master { - d.cancel() - } return nil } @@ -328,7 +325,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode err := d.synchronise(id, head, td, mode) switch err { case nil: - case errBusy: + case errBusy, errCanceled: case errTimeout, errBadPeer, errStallingPeer, errUnsyncedPeer, errEmptyHeaderSet, errPeersUnavailable, errTooOld, @@ -365,6 +362,12 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode if atomic.CompareAndSwapInt32(&d.notified, 0, 1) { log.Info("Block synchronisation started") } + // If we are already full syncing, but have a fast-sync bloom filter laying + // around, make sure it does't use memory any more. This is a special case + // when the user attempts to fast sync a new empty network. + if mode == FullSync && d.stateBloom != nil { + d.stateBloom.Close() + } // Reset the queue, peer set and wake channels to clean any internal leftover state d.queue.Reset() d.peers.Reset() @@ -421,7 +424,8 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I if err != nil { d.mux.Post(FailedEvent{err}) } else { - d.mux.Post(DoneEvent{}) + latest := d.lightchain.CurrentHeader() + d.mux.Post(DoneEvent{latest}) } }() if p.version < 62 { @@ -430,7 +434,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I log.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "td", td, "mode", d.mode) defer func(start time.Time) { - log.Debug("Synchronisation terminated", "elapsed", time.Since(start)) + log.Debug("Synchronisation terminated", "elapsed", common.PrettyDuration(time.Since(start))) }(time.Now()) // Look up the sync boundaries: the common ancestor and the target block @@ -467,12 +471,49 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I if d.mode == FastSync && pivot != 0 { d.committed = 0 } + if d.mode == FastSync { + // Set the ancient data limitation. + // If we are running fast sync, all block data older than ancientLimit will be + // written to the ancient store. More recent data will be written to the active + // database and will wait for the freezer to migrate. + // + // If there is a checkpoint available, then calculate the ancientLimit through + // that. Otherwise calculate the ancient limit through the advertised height + // of the remote peer. + // + // The reason for picking checkpoint first is that a malicious peer can give us + // a fake (very high) height, forcing the ancient limit to also be very high. + // The peer would start to feed us valid blocks until head, resulting in all of + // the blocks might be written into the ancient store. A following mini-reorg + // could cause issues. + if d.checkpoint != 0 && d.checkpoint > maxForkAncestry+1 { + d.ancientLimit = d.checkpoint + } else if height > maxForkAncestry+1 { + d.ancientLimit = height - maxForkAncestry - 1 + } + frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here. + // If a part of blockchain data has already been written into active store, + // disable the ancient style insertion explicitly. + if origin >= frozen && frozen != 0 { + d.ancientLimit = 0 + log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", frozen-1) + } else if d.ancientLimit > 0 { + log.Debug("Enabling direct-ancient mode", "ancient", d.ancientLimit) + } + // Rewind the ancient store and blockchain if reorg happens. + if origin+1 < frozen { + var hashes []common.Hash + for i := origin + 1; i < d.lightchain.CurrentHeader().Number.Uint64(); i++ { + hashes = append(hashes, rawdb.ReadCanonicalHash(d.stateDB, i)) + } + d.lightchain.Rollback(hashes) + } + } // Initiate the sync using a concurrent header and content retrieval algorithm d.queue.Prepare(origin+1, d.mode) if d.syncInitHook != nil { d.syncInitHook(origin, height) } - fetchers := []func() error{ func() error { return d.fetchHeaders(p, origin+1, pivot) }, // Headers are always retrieved func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync @@ -484,19 +525,12 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I } else if d.mode == FullSync { fetchers = append(fetchers, d.processFullSyncContent) } - return d.spawnSync(errCancelHeaderFetch, fetchers) + return d.spawnSync(fetchers) } // spawnSync runs d.process and all given fetcher functions to completion in // separate goroutines, returning the first error that appears. -func (d *Downloader) spawnSync(errCancel error, fetchers []func() error) error { - d.cancelLock.Lock() - select { - case <-d.cancelCh: - d.cancelLock.Unlock() - return errCancel - default: - } +func (d *Downloader) spawnSync(fetchers []func() error) error { errc := make(chan error, len(fetchers)) d.cancelWg.Add(len(fetchers)) d.cancelLock.Unlock() @@ -513,7 +547,7 @@ func (d *Downloader) spawnSync(errCancel error, fetchers []func() error) error { // it has processed the queue. d.queue.Close() } - if err = <-errc; err != nil { + if err = <-errc; err != nil && err != errCanceled { break } } @@ -544,6 +578,9 @@ func (d *Downloader) cancel() { func (d *Downloader) Cancel() { d.cancel() d.cancelWg.Wait() + + d.ancientLimit = 0 + log.Debug("Reset ancient limit to zero") } // Terminate interrupts the downloader, canceling all pending operations. @@ -580,7 +617,7 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { for { select { case <-d.cancelCh: - return nil, errCancelBlockFetch + return nil, errCanceled case packet := <-d.headerCh: // Discard anything not from the origin peer @@ -595,7 +632,7 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) { return nil, errBadPeer } head := headers[0] - if d.mode == FastSync && head.Number.Uint64() < d.checkpoint { + if (d.mode == FastSync || d.mode == LightSync) && head.Number.Uint64() < d.checkpoint { p.log.Warn("Remote head below checkpoint", "number", head.Number, "hash", head.Hash()) return nil, errUnsyncedPeer } @@ -686,30 +723,32 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) localHeight = d.lightchain.CurrentHeader().Number.Uint64() } p.log.Debug("Looking for common ancestor", "local", localHeight, "remote", remoteHeight) - if localHeight >= MaxForkAncestry { - // We're above the max reorg threshold, find the earliest fork point - floor = int64(localHeight - MaxForkAncestry) - // If we're doing a light sync, ensure the floor doesn't go below the CHT, as - // all headers before that point will be missing. - if d.mode == LightSync { - // If we dont know the current CHT position, find it - if d.genesis == 0 { - header := d.lightchain.CurrentHeader() - for header != nil { - d.genesis = header.Number.Uint64() - if floor >= int64(d.genesis)-1 { - break - } - header = d.lightchain.GetHeaderByHash(header.ParentHash) + // Recap floor value for binary search + if localHeight >= maxForkAncestry { + // We're above the max reorg threshold, find the earliest fork point + floor = int64(localHeight - maxForkAncestry) + } + // If we're doing a light sync, ensure the floor doesn't go below the CHT, as + // all headers before that point will be missing. + if d.mode == LightSync { + // If we dont know the current CHT position, find it + if d.genesis == 0 { + header := d.lightchain.CurrentHeader() + for header != nil { + d.genesis = header.Number.Uint64() + if floor >= int64(d.genesis)-1 { + break } - } - // We already know the "genesis" block number, cap floor to that - if floor < int64(d.genesis)-1 { - floor = int64(d.genesis) - 1 + header = d.lightchain.GetHeaderByHash(header.ParentHash) } } + // We already know the "genesis" block number, cap floor to that + if floor < int64(d.genesis)-1 { + floor = int64(d.genesis) - 1 + } } + from, count, skip, max := calculateRequestSpan(remoteHeight, localHeight) p.log.Trace("Span searching for common ancestor", "count", count, "from", from, "skip", skip) @@ -724,7 +763,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) for finished := false; !finished; { select { case <-d.cancelCh: - return 0, errCancelHeaderFetch + return 0, errCanceled case packet := <-d.headerCh: // Discard anything not from the origin peer @@ -740,7 +779,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) } // Make sure the peer's reply conforms to the request for i, header := range headers { - expectNumber := from + int64(i)*int64((skip+1)) + expectNumber := from + int64(i)*int64(skip+1) if number := header.Number.Int64(); number != expectNumber { p.log.Warn("Head headers broke chain ordering", "index", i, "requested", expectNumber, "received", number) return 0, errInvalidChain @@ -810,7 +849,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) for arrived := false; !arrived; { select { case <-d.cancelCh: - return 0, errCancelHeaderFetch + return 0, errCanceled case packer := <-d.headerCh: // Discard anything not from the origin peer @@ -905,12 +944,13 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) } } // Start pulling the header chain skeleton until all is done + ancestor := from getHeaders(from) for { select { case <-d.cancelCh: - return errCancelHeaderFetch + return errCanceled case packet := <-d.headerCh: // Make sure the active peer is giving us the skeleton headers @@ -937,7 +977,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) getHeaders(from) continue case <-d.cancelCh: - return errCancelHeaderFetch + return errCanceled } } // Pivot done (or not in fast sync) and no more headers, terminate the process @@ -946,7 +986,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) case d.headerProcCh <- nil: return nil case <-d.cancelCh: - return errCancelHeaderFetch + return errCanceled } } headers := packet.(*headerPack).headers @@ -966,7 +1006,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) // chain errors. if n := len(headers); n > 0 { // Retrieve the current head we're at - head := uint64(0) + var head uint64 if d.mode == LightSync { head = d.lightchain.CurrentHeader().Number.Uint64() } else { @@ -975,6 +1015,12 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) head = full } } + // If the head is below the common ancestor, we're actually deduplicating + // already existing chain segments, so use the ancestor as the fake head. + // Otherwise we might end up delaying header deliveries pointlessly. + if head < ancestor { + head = ancestor + } // If the head is way older than this batch, delay the last few headers if head+uint64(reorgProtThreshold) < headers[n-1].Number.Uint64() { delay := reorgProtHeaderDelay @@ -991,7 +1037,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) select { case d.headerProcCh <- headers: case <-d.cancelCh: - return errCancelHeaderFetch + return errCanceled } from += uint64(len(headers)) getHeaders(from) @@ -1003,7 +1049,7 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) getHeaders(from) continue case <-d.cancelCh: - return errCancelHeaderFetch + return errCanceled } } @@ -1062,7 +1108,7 @@ func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ( capacity = func(p *peerConnection) int { return p.HeaderCapacity(d.requestRTT()) } setIdle = func(p *peerConnection, accepted int) { p.SetHeadersIdle(accepted) } ) - err := d.fetchParts(errCancelHeaderFetch, d.headerCh, deliver, d.queue.headerContCh, expire, + err := d.fetchParts(d.headerCh, deliver, d.queue.headerContCh, expire, d.queue.PendingHeaders, d.queue.InFlightHeaders, throttle, reserve, nil, fetch, d.queue.CancelHeaders, capacity, d.peers.HeaderIdlePeers, setIdle, "headers") @@ -1088,7 +1134,7 @@ func (d *Downloader) fetchBodies(from uint64) error { capacity = func(p *peerConnection) int { return p.BlockCapacity(d.requestRTT()) } setIdle = func(p *peerConnection, accepted int) { p.SetBodiesIdle(accepted) } ) - err := d.fetchParts(errCancelBodyFetch, d.bodyCh, deliver, d.bodyWakeCh, expire, + err := d.fetchParts(d.bodyCh, deliver, d.bodyWakeCh, expire, d.queue.PendingBlocks, d.queue.InFlightBlocks, d.queue.ShouldThrottleBlocks, d.queue.ReserveBodies, d.bodyFetchHook, fetch, d.queue.CancelBodies, capacity, d.peers.BodyIdlePeers, setIdle, "bodies") @@ -1112,7 +1158,7 @@ func (d *Downloader) fetchReceipts(from uint64) error { capacity = func(p *peerConnection) int { return p.ReceiptCapacity(d.requestRTT()) } setIdle = func(p *peerConnection, accepted int) { p.SetReceiptsIdle(accepted) } ) - err := d.fetchParts(errCancelReceiptFetch, d.receiptCh, deliver, d.receiptWakeCh, expire, + err := d.fetchParts(d.receiptCh, deliver, d.receiptWakeCh, expire, d.queue.PendingReceipts, d.queue.InFlightReceipts, d.queue.ShouldThrottleReceipts, d.queue.ReserveReceipts, d.receiptFetchHook, fetch, d.queue.CancelReceipts, capacity, d.peers.ReceiptIdlePeers, setIdle, "receipts") @@ -1145,7 +1191,7 @@ func (d *Downloader) fetchReceipts(from uint64) error { // - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks // - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping) // - kind: textual label of the type being downloaded to display in log mesages -func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool, +func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool, expire func() map[string]int, pending func() int, inFlight func() bool, throttle func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, error), fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int, idle func() ([]*peerConnection, int), setIdle func(*peerConnection, int), kind string) error { @@ -1161,7 +1207,7 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv for { select { case <-d.cancelCh: - return errCancel + return errCanceled case packet := <-deliveryCh: // If the peer was previously banned and failed to deliver its pack @@ -1232,12 +1278,23 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv setIdle(peer, 0) } else { peer.log.Debug("Stalling delivery, dropping", "type", kind) + if d.dropPeer == nil { // The dropPeer method is nil when `--copydb` is used for a local copy. // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", pid) } else { d.dropPeer(pid) + + // If this peer was the master peer, abort sync immediately + d.cancelLock.RLock() + master := pid == d.cancelPeer + d.cancelLock.RUnlock() + + if master { + d.cancel() + return errTimeout + } } } } @@ -1310,7 +1367,7 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv // queue until the stream ends or a failure occurs. func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error { // Keep a count of uncertain headers to roll back - rollback := []*types.Header{} + var rollback []*types.Header defer func() { if len(rollback) > 0 { // Flatten the headers and roll them back @@ -1342,7 +1399,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er for { select { case <-d.cancelCh: - return errCancelHeaderProcessing + return errCanceled case headers := <-d.headerProcCh: // Terminate header processing if we synced up @@ -1391,12 +1448,11 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er } // Otherwise split the chunk of headers into batches and process them gotHeaders = true - for len(headers) > 0 { // Terminate if something failed in between processing chunks select { case <-d.cancelCh: - return errCancelHeaderProcessing + return errCanceled default: } // Select the next chunk of headers to import @@ -1405,11 +1461,10 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er limit = len(headers) } chunk := headers[:limit] - // In case of header only syncing, validate the chunk immediately if d.mode == FastSync || d.mode == LightSync { // Collect the yet unknown headers to mark them as uncertain - unknown := make([]*types.Header, 0, len(headers)) + unknown := make([]*types.Header, 0, len(chunk)) for _, header := range chunk { if !d.lightchain.HasHeader(header.Hash(), header.Number.Uint64()) { unknown = append(unknown, header) @@ -1440,7 +1495,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er for d.queue.PendingBlocks() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { select { case <-d.cancelCh: - return errCancelHeaderProcessing + return errCanceled case <-time.After(time.Second): } } @@ -1454,7 +1509,6 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er headers = headers[limit:] origin += uint64(limit) } - // Update the highest block number we know if a higher one is found. d.syncStatsLock.Lock() if d.syncStatsChainHeight < origin { @@ -1532,7 +1586,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { stateSync := d.syncState(latest.Root) defer stateSync.Cancel() go func() { - if err := stateSync.Wait(); err != nil && err != errCancelStateFetch { + if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled { d.queue.Close() // wake up Results } }() @@ -1560,7 +1614,8 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { // If sync failed, stop select { case <-d.cancelCh: - return stateSync.Cancel() + stateSync.Cancel() + return errCanceled default: } } @@ -1590,7 +1645,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error { stateSync = d.syncState(P.Header.Root) defer stateSync.Cancel() go func() { - if err := stateSync.Wait(); err != nil && err != errCancelStateFetch { + if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled { d.queue.Close() // wake up Results } }() @@ -1660,7 +1715,7 @@ func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *state blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) receipts[i] = result.Receipts } - if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil { + if index, err := d.blockchain.InsertReceiptChain(blocks, receipts, d.ancientLimit); err != nil { log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) return errInvalidChain } @@ -1670,13 +1725,24 @@ func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *state func (d *Downloader) commitPivotBlock(result *fetchResult) error { block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) log.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash()) - if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil { + + // Commit the pivot block as the new head, will require full sync from here on + if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}, d.ancientLimit); err != nil { return err } if err := d.blockchain.FastSyncCommitHead(block.Hash()); err != nil { return err } atomic.StoreInt32(&d.committed, 1) + + // If we had a bloom filter for the state sync, deallocate it now. Note, we only + // deallocate internally, but keep the empty wrapper. This ensures that if we do + // a rollback after committing the pivot and restarting fast sync, we don't end + // up using a nil bloom. Empty bloom is fine, it just returns that it does not + // have the info we need, so reach down to the database instead. + if d.stateBloom != nil { + d.stateBloom.Close() + } return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/events.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/events.go index 64905b8f2..25255a3a7 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/events.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/events.go @@ -16,6 +16,10 @@ package downloader -type DoneEvent struct{} +import "github.com/ethereum/go-ethereum/core/types" + +type DoneEvent struct { + Latest *types.Header +} type StartEvent struct{} type FailedEvent struct{ Err error } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/fakepeer.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/fakepeer.go index 59832faca..3ec90bc9e 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/fakepeer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/fakepeer.go @@ -141,7 +141,7 @@ func (p *FakePeer) RequestBodies(hashes []common.Hash) error { func (p *FakePeer) RequestReceipts(hashes []common.Hash) error { var receipts [][]*types.Receipt for _, hash := range hashes { - receipts = append(receipts, rawdb.ReadReceipts(p.db, hash, *p.hc.GetBlockNumber(hash))) + receipts = append(receipts, rawdb.ReadRawReceipts(p.db, hash, *p.hc.GetBlockNumber(hash))) } p.dl.DeliverReceipts(p.id, receipts) return nil diff --git a/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go b/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go index 0675a91cd..b422557d5 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/downloader/statesync.go @@ -59,6 +59,7 @@ type stateSyncStats struct { // syncState starts downloading state with the given root hash. func (d *Downloader) syncState(root common.Hash) *stateSync { + // Create the state sync s := newStateSync(d, root) select { case d.stateSyncStart <- s: @@ -239,7 +240,7 @@ type stateTask struct { func newStateSync(d *Downloader, root common.Hash) *stateSync { return &stateSync{ d: d, - sched: state.NewStateSync(root, d.stateDB), + sched: state.NewStateSync(root, d.stateDB, d.stateBloom), keccak: sha3.NewLegacyKeccak256(), tasks: make(map[common.Hash]*stateTask), deliver: make(chan *stateReq), @@ -301,7 +302,7 @@ func (s *stateSync) loop() (err error) { return errCancelStateFetch case <-s.d.cancelCh: - return errCancelStateFetch + return errCanceled case req := <-s.deliver: // Response, disconnect or timeout triggered, drop the peer if stalling @@ -310,7 +311,23 @@ func (s *stateSync) loop() (err error) { // 2 items are the minimum requested, if even that times out, we've no use of // this peer at the moment. log.Warn("Stalling state sync, dropping peer", "peer", req.peer.id) - s.d.dropPeer(req.peer.id) + if s.d.dropPeer == nil { + // The dropPeer method is nil when `--copydb` is used for a local copy. + // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored + req.peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", req.peer.id) + } else { + s.d.dropPeer(req.peer.id) + + // If this peer was the master peer, abort sync immediately + s.d.cancelLock.RLock() + master := req.peer.id == s.d.cancelPeer + s.d.cancelLock.RUnlock() + + if master { + s.d.cancel() + return errTimeout + } + } } // Process all the received blobs and check for stale delivery delivered, err := s.process(req) @@ -425,9 +442,7 @@ func (s *stateSync) process(req *stateReq) (int, error) { default: return successful, fmt.Errorf("invalid state node %s: %v", hash.TerminalString(), err) } - if _, ok := req.tasks[hash]; ok { - delete(req.tasks, hash) - } + delete(req.tasks, hash) } // Put unfulfilled tasks back into the retry queue npeers := s.d.peers.Len() diff --git a/vendor/github.com/ethereum/go-ethereum/eth/enr_entry.go b/vendor/github.com/ethereum/go-ethereum/eth/enr_entry.go new file mode 100644 index 000000000..d9e7b9578 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/eth/enr_entry.go @@ -0,0 +1,61 @@ +// Copyright 2019 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 eth + +import ( + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/forkid" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/rlp" +) + +// ethEntry is the "eth" ENR entry which advertises eth protocol +// on the discovery network. +type ethEntry struct { + ForkID forkid.ID // Fork identifier per EIP-2124 + + // Ignore additional fields (for forward compatibility). + Rest []rlp.RawValue `rlp:"tail"` +} + +// ENRKey implements enr.Entry. +func (e ethEntry) ENRKey() string { + return "eth" +} + +func (eth *Ethereum) startEthEntryUpdate(ln *enode.LocalNode) { + var newHead = make(chan core.ChainHeadEvent, 10) + sub := eth.blockchain.SubscribeChainHeadEvent(newHead) + + go func() { + defer sub.Unsubscribe() + for { + select { + case <-newHead: + ln.Set(eth.currentEthEntry()) + case <-sub.Err(): + // Would be nice to sync with eth.Stop, but there is no + // good way to do that. + return + } + } + }() +} + +func (eth *Ethereum) currentEthEntry() *ethEntry { + return ðEntry{ForkID: forkid.NewID(eth.blockchain)} +} diff --git a/vendor/github.com/ethereum/go-ethereum/eth/fetcher/fetcher.go b/vendor/github.com/ethereum/go-ethereum/eth/fetcher/fetcher.go index f0b5e8064..28c532d9b 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/fetcher/fetcher.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/fetcher/fetcher.go @@ -110,7 +110,6 @@ type Fetcher struct { notify chan *announce inject chan *inject - blockFilter chan chan []*types.Block headerFilter chan chan *headerFilterTask bodyFilter chan chan *bodyFilterTask @@ -150,7 +149,6 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBloc return &Fetcher{ notify: make(chan *announce), inject: make(chan *inject), - blockFilter: make(chan chan []*types.Block), headerFilter: make(chan chan *headerFilterTask), bodyFilter: make(chan chan *bodyFilterTask), done: make(chan common.Hash), @@ -687,7 +685,7 @@ func (f *Fetcher) forgetHash(hash common.Hash) { // Remove all pending announces and decrement DOS counters for _, announce := range f.announced[hash] { f.announces[announce.origin]-- - if f.announces[announce.origin] == 0 { + if f.announces[announce.origin] <= 0 { delete(f.announces, announce.origin) } } @@ -698,7 +696,7 @@ func (f *Fetcher) forgetHash(hash common.Hash) { // Remove any pending fetches and decrement the DOS counters if announce := f.fetching[hash]; announce != nil { f.announces[announce.origin]-- - if f.announces[announce.origin] == 0 { + if f.announces[announce.origin] <= 0 { delete(f.announces, announce.origin) } delete(f.fetching, hash) @@ -707,7 +705,7 @@ func (f *Fetcher) forgetHash(hash common.Hash) { // Remove any pending completion requests and decrement the DOS counters for _, announce := range f.fetched[hash] { f.announces[announce.origin]-- - if f.announces[announce.origin] == 0 { + if f.announces[announce.origin] <= 0 { delete(f.announces, announce.origin) } } @@ -716,7 +714,7 @@ func (f *Fetcher) forgetHash(hash common.Hash) { // Remove any pending completions and decrement the DOS counters if announce := f.completing[hash]; announce != nil { f.announces[announce.origin]-- - if f.announces[announce.origin] == 0 { + if f.announces[announce.origin] <= 0 { delete(f.announces, announce.origin) } delete(f.completing, hash) diff --git a/vendor/github.com/ethereum/go-ethereum/eth/gen_config.go b/vendor/github.com/ethereum/go-ethereum/eth/gen_config.go index 6662f820f..bc4b55b12 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/gen_config.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/gen_config.go @@ -7,15 +7,14 @@ import ( "time" "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/eth/downloader" "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/miner" + "github.com/ethereum/go-ethereum/params" ) -var _ = (*configMarshaling)(nil) - // MarshalTOML marshals as TOML. func (c Config) MarshalTOML() (interface{}, error) { type Config struct { @@ -23,24 +22,23 @@ func (c Config) MarshalTOML() (interface{}, error) { NetworkId uint64 SyncMode downloader.SyncMode NoPruning bool - LightServ int `toml:",omitempty"` - LightPeers int `toml:",omitempty"` - OnlyAnnounce bool - ULC *ULCConfig `toml:",omitempty"` - SkipBcVersionCheck bool `toml:"-"` - DatabaseHandles int `toml:"-"` + NoPrefetch bool + Whitelist map[uint64]common.Hash `toml:"-"` + LightServ int `toml:",omitempty"` + LightIngress int `toml:",omitempty"` + LightEgress int `toml:",omitempty"` + LightPeers int `toml:",omitempty"` + UltraLightServers []string `toml:",omitempty"` + UltraLightFraction int `toml:",omitempty"` + UltraLightOnlyAnnounce bool `toml:",omitempty"` + SkipBcVersionCheck bool `toml:"-"` + DatabaseHandles int `toml:"-"` DatabaseCache int + DatabaseFreezer string TrieCleanCache int TrieDirtyCache int TrieTimeout time.Duration - Etherbase common.Address `toml:",omitempty"` - MinerNotify []string `toml:",omitempty"` - MinerExtraData hexutil.Bytes `toml:",omitempty"` - MinerGasFloor uint64 - MinerGasCeil uint64 - MinerGasPrice *big.Int - MinerRecommit time.Duration - MinerNoverify bool + Miner miner.Config Ethash ethash.Config TxPool core.TxPoolConfig GPO gasprice.Config @@ -48,30 +46,32 @@ func (c Config) MarshalTOML() (interface{}, error) { DocRoot string `toml:"-"` EWASMInterpreter string EVMInterpreter string + RPCGasCap *big.Int `toml:",omitempty"` + Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` + CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` } var enc Config enc.Genesis = c.Genesis enc.NetworkId = c.NetworkId enc.SyncMode = c.SyncMode enc.NoPruning = c.NoPruning + enc.NoPrefetch = c.NoPrefetch + enc.Whitelist = c.Whitelist enc.LightServ = c.LightServ + enc.LightIngress = c.LightIngress + enc.LightEgress = c.LightEgress enc.LightPeers = c.LightPeers - enc.OnlyAnnounce = c.OnlyAnnounce - enc.ULC = c.ULC + enc.UltraLightServers = c.UltraLightServers + enc.UltraLightFraction = c.UltraLightFraction + enc.UltraLightOnlyAnnounce = c.UltraLightOnlyAnnounce enc.SkipBcVersionCheck = c.SkipBcVersionCheck enc.DatabaseHandles = c.DatabaseHandles enc.DatabaseCache = c.DatabaseCache + enc.DatabaseFreezer = c.DatabaseFreezer enc.TrieCleanCache = c.TrieCleanCache enc.TrieDirtyCache = c.TrieDirtyCache enc.TrieTimeout = c.TrieTimeout - enc.Etherbase = c.Etherbase - enc.MinerNotify = c.MinerNotify - enc.MinerExtraData = c.MinerExtraData - enc.MinerGasFloor = c.MinerGasFloor - enc.MinerGasCeil = c.MinerGasCeil - enc.MinerGasPrice = c.MinerGasPrice - enc.MinerRecommit = c.MinerRecommit - enc.MinerNoverify = c.MinerNoverify + enc.Miner = c.Miner enc.Ethash = c.Ethash enc.TxPool = c.TxPool enc.GPO = c.GPO @@ -79,6 +79,9 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.DocRoot = c.DocRoot enc.EWASMInterpreter = c.EWASMInterpreter enc.EVMInterpreter = c.EVMInterpreter + enc.RPCGasCap = c.RPCGasCap + enc.Checkpoint = c.Checkpoint + enc.CheckpointOracle = c.CheckpointOracle return &enc, nil } @@ -89,24 +92,23 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { NetworkId *uint64 SyncMode *downloader.SyncMode NoPruning *bool - LightServ *int `toml:",omitempty"` - LightPeers *int `toml:",omitempty"` - OnlyAnnounce *bool - ULC *ULCConfig `toml:",omitempty"` - SkipBcVersionCheck *bool `toml:"-"` - DatabaseHandles *int `toml:"-"` + NoPrefetch *bool + Whitelist map[uint64]common.Hash `toml:"-"` + LightServ *int `toml:",omitempty"` + LightIngress *int `toml:",omitempty"` + LightEgress *int `toml:",omitempty"` + LightPeers *int `toml:",omitempty"` + UltraLightServers []string `toml:",omitempty"` + UltraLightFraction *int `toml:",omitempty"` + UltraLightOnlyAnnounce *bool `toml:",omitempty"` + SkipBcVersionCheck *bool `toml:"-"` + DatabaseHandles *int `toml:"-"` DatabaseCache *int + DatabaseFreezer *string TrieCleanCache *int TrieDirtyCache *int TrieTimeout *time.Duration - Etherbase *common.Address `toml:",omitempty"` - MinerNotify []string `toml:",omitempty"` - MinerExtraData *hexutil.Bytes `toml:",omitempty"` - MinerGasFloor *uint64 - MinerGasCeil *uint64 - MinerGasPrice *big.Int - MinerRecommit *time.Duration - MinerNoverify *bool + Miner *miner.Config Ethash *ethash.Config TxPool *core.TxPoolConfig GPO *gasprice.Config @@ -114,6 +116,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { DocRoot *string `toml:"-"` EWASMInterpreter *string EVMInterpreter *string + RPCGasCap *big.Int `toml:",omitempty"` + Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` + CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` } var dec Config if err := unmarshal(&dec); err != nil { @@ -131,17 +136,32 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.NoPruning != nil { c.NoPruning = *dec.NoPruning } + if dec.NoPrefetch != nil { + c.NoPrefetch = *dec.NoPrefetch + } + if dec.Whitelist != nil { + c.Whitelist = dec.Whitelist + } if dec.LightServ != nil { c.LightServ = *dec.LightServ } + if dec.LightIngress != nil { + c.LightIngress = *dec.LightIngress + } + if dec.LightEgress != nil { + c.LightEgress = *dec.LightEgress + } if dec.LightPeers != nil { c.LightPeers = *dec.LightPeers } - if dec.OnlyAnnounce != nil { - c.OnlyAnnounce = *dec.OnlyAnnounce + if dec.UltraLightServers != nil { + c.UltraLightServers = dec.UltraLightServers } - if dec.ULC != nil { - c.ULC = dec.ULC + if dec.UltraLightFraction != nil { + c.UltraLightFraction = *dec.UltraLightFraction + } + if dec.UltraLightOnlyAnnounce != nil { + c.UltraLightOnlyAnnounce = *dec.UltraLightOnlyAnnounce } if dec.SkipBcVersionCheck != nil { c.SkipBcVersionCheck = *dec.SkipBcVersionCheck @@ -152,6 +172,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.DatabaseCache != nil { c.DatabaseCache = *dec.DatabaseCache } + if dec.DatabaseFreezer != nil { + c.DatabaseFreezer = *dec.DatabaseFreezer + } if dec.TrieCleanCache != nil { c.TrieCleanCache = *dec.TrieCleanCache } @@ -161,29 +184,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.TrieTimeout != nil { c.TrieTimeout = *dec.TrieTimeout } - if dec.Etherbase != nil { - c.Etherbase = *dec.Etherbase - } - if dec.MinerNotify != nil { - c.MinerNotify = dec.MinerNotify - } - if dec.MinerExtraData != nil { - c.MinerExtraData = *dec.MinerExtraData - } - if dec.MinerGasFloor != nil { - c.MinerGasFloor = *dec.MinerGasFloor - } - if dec.MinerGasCeil != nil { - c.MinerGasCeil = *dec.MinerGasCeil - } - if dec.MinerGasPrice != nil { - c.MinerGasPrice = dec.MinerGasPrice - } - if dec.MinerRecommit != nil { - c.MinerRecommit = *dec.MinerRecommit - } - if dec.MinerNoverify != nil { - c.MinerNoverify = *dec.MinerNoverify + if dec.Miner != nil { + c.Miner = *dec.Miner } if dec.Ethash != nil { c.Ethash = *dec.Ethash @@ -206,5 +208,14 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.EVMInterpreter != nil { c.EVMInterpreter = *dec.EVMInterpreter } + if dec.RPCGasCap != nil { + c.RPCGasCap = dec.RPCGasCap + } + if dec.Checkpoint != nil { + c.Checkpoint = dec.Checkpoint + } + if dec.CheckpointOracle != nil { + c.CheckpointOracle = dec.CheckpointOracle + } return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/eth/handler.go b/vendor/github.com/ethereum/go-ethereum/eth/handler.go index f9e7042c6..4ce2d1c82 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/handler.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/handler.go @@ -39,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" ) const ( @@ -57,10 +58,6 @@ var ( syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge ) -// errIncompatibleConfig is returned if the requested protocols and configs are -// not compatible (low protocol version restrictions and high requirements). -var errIncompatibleConfig = errors.New("incompatible configuration") - func errResp(code errCode, format string, v ...interface{}) error { return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) } @@ -74,17 +71,14 @@ type ProtocolManager struct { checkpointNumber uint64 // Block number for the sync progress validator to cross reference checkpointHash common.Hash // Block hash for the sync progress validator to cross reference - txpool txPool - blockchain *core.BlockChain - chainconfig *params.ChainConfig - maxPeers int + txpool txPool + blockchain *core.BlockChain + maxPeers int downloader *downloader.Downloader fetcher *fetcher.Fetcher peers *peerSet - SubProtocols []p2p.Protocol - eventMux *event.TypeMux txsCh chan core.NewTxsEvent txsSub event.Subscription @@ -105,14 +99,13 @@ type ProtocolManager struct { // NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the Ethereum network. -func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database, whitelist map[uint64]common.Hash) (*ProtocolManager, error) { +func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCheckpoint, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database, cacheLimit int, whitelist map[uint64]common.Hash) (*ProtocolManager, error) { // Create the protocol manager with the base fields manager := &ProtocolManager{ networkID: networkID, eventMux: mux, txpool: txpool, blockchain: blockchain, - chainconfig: config, peers: newPeerSet(), whitelist: whitelist, newPeerCh: make(chan *peer), @@ -120,60 +113,45 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne txsyncCh: make(chan *txsync), quitSync: make(chan struct{}), } - // Figure out whether to allow fast sync or not - if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 { - log.Warn("Blockchain not empty, fast sync disabled") - mode = downloader.FullSync - } - if mode == downloader.FastSync { - manager.fastSync = uint32(1) + if mode == downloader.FullSync { + // The database seems empty as the current block is the genesis. Yet the fast + // block is ahead, so fast sync was enabled for this node at a certain point. + // The scenarios where this can happen is + // * if the user manually (or via a bad block) rolled back a fast sync node + // below the sync point. + // * the last fast sync is not finished while user specifies a full sync this + // time. But we don't have any recent state for full sync. + // In these cases however it's safe to reenable fast sync. + fullBlock, fastBlock := blockchain.CurrentBlock(), blockchain.CurrentFastBlock() + if fullBlock.NumberU64() == 0 && fastBlock.NumberU64() > 0 { + manager.fastSync = uint32(1) + log.Warn("Switch sync mode from full sync to fast sync") + } + } else { + if blockchain.CurrentBlock().NumberU64() > 0 { + // Print warning log if database is not empty to run fast sync. + log.Warn("Switch sync mode from fast sync to full sync") + } else { + // If fast sync was requested and our database is empty, grant it + manager.fastSync = uint32(1) + } } // If we have trusted checkpoints, enforce them on the chain - if checkpoint, ok := params.TrustedCheckpoints[blockchain.Genesis().Hash()]; ok { - manager.checkpointNumber = (checkpoint.SectionIndex+1)*params.CHTFrequencyClient - 1 + if checkpoint != nil { + manager.checkpointNumber = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 manager.checkpointHash = checkpoint.SectionHead } - // Initiate a sub-protocol for every implemented version we can handle - manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions)) - for i, version := range ProtocolVersions { - // Skip protocol version if incompatible with the mode of operation - if mode == downloader.FastSync && version < eth63 { - continue - } - // Compatible; initialise the sub-protocol - version := version // Closure for the run - manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{ - Name: ProtocolName, - Version: version, - Length: ProtocolLengths[i], - Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - peer := manager.newPeer(int(version), p, rw) - select { - case manager.newPeerCh <- peer: - manager.wg.Add(1) - defer manager.wg.Done() - return manager.handle(peer) - case <-manager.quitSync: - return p2p.DiscQuitting - } - }, - NodeInfo: func() interface{} { - return manager.NodeInfo() - }, - PeerInfo: func(id enode.ID) interface{} { - if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil { - return p.Info() - } - return nil - }, - }) - } - if len(manager.SubProtocols) == 0 { - return nil, errIncompatibleConfig - } - // Construct the different synchronisation mechanisms - manager.downloader = downloader.New(mode, manager.checkpointNumber, chaindb, manager.eventMux, blockchain, nil, manager.removePeer) + // Construct the downloader (long sync) and its backing state bloom if fast + // sync is requested. The downloader is responsible for deallocating the state + // bloom when it's done. + var stateBloom *trie.SyncBloom + if atomic.LoadUint32(&manager.fastSync) == 1 { + stateBloom = trie.NewSyncBloom(uint64(cacheLimit), chaindb) + } + manager.downloader = downloader.New(manager.checkpointNumber, chaindb, stateBloom, manager.eventMux, blockchain, nil, manager.removePeer) + + // Construct the fetcher (short sync) validator := func(header *types.Header) error { return engine.VerifyHeader(blockchain, header, true) } @@ -181,19 +159,69 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne return blockchain.CurrentBlock().NumberU64() } inserter := func(blocks types.Blocks) (int, error) { - // If fast sync is running, deny importing weird blocks - if atomic.LoadUint32(&manager.fastSync) == 1 { - log.Warn("Discarded bad propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) + // If sync hasn't reached the checkpoint yet, deny importing weird blocks. + // + // Ideally we would also compare the head block's timestamp and similarly reject + // the propagated block if the head is too old. Unfortunately there is a corner + // case when starting new networks, where the genesis might be ancient (0 unix) + // which would prevent full nodes from accepting it. + if manager.blockchain.CurrentBlock().NumberU64() < manager.checkpointNumber { + log.Warn("Unsynced yet, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) return 0, nil } - atomic.StoreUint32(&manager.acceptTxs, 1) // Mark initial sync done on any fetcher import - return manager.blockchain.InsertChain(blocks) + // If fast sync is running, deny importing weird blocks. This is a problematic + // clause when starting up a new network, because fast-syncing miners might not + // accept each others' blocks until a restart. Unfortunately we haven't figured + // out a way yet where nodes can decide unilaterally whether the network is new + // or not. This should be fixed if we figure out a solution. + if atomic.LoadUint32(&manager.fastSync) == 1 { + log.Warn("Fast syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) + return 0, nil + } + n, err := manager.blockchain.InsertChain(blocks) + if err == nil { + atomic.StoreUint32(&manager.acceptTxs, 1) // Mark initial sync done on any fetcher import + } + return n, err } manager.fetcher = fetcher.New(blockchain.GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) return manager, nil } +func (pm *ProtocolManager) makeProtocol(version uint) p2p.Protocol { + length, ok := protocolLengths[version] + if !ok { + panic("makeProtocol for unknown version") + } + + return p2p.Protocol{ + Name: protocolName, + Version: version, + Length: length, + Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { + peer := pm.newPeer(int(version), p, rw) + select { + case pm.newPeerCh <- peer: + pm.wg.Add(1) + defer pm.wg.Done() + return pm.handle(peer) + case <-pm.quitSync: + return p2p.DiscQuitting + } + }, + NodeInfo: func() interface{} { + return pm.NodeInfo() + }, + PeerInfo: func(id enode.ID) interface{} { + if p := pm.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil { + return p.Info() + } + return nil + }, + } +} + func (pm *ProtocolManager) removePeer(id string) { // Short circuit if the peer was already removed peer := pm.peers.Peer(id) @@ -243,9 +271,6 @@ func (pm *ProtocolManager) Stop() { // Quit fetcher, txsyncLoop. close(pm.quitSync) - // Stop downloader and make sure that all the running downloads are complete. - pm.downloader.Terminate() - // Disconnect existing sessions. // This also closes the gate for any new registrations on the peer set. // sessions which are already established but not added to pm.peers yet @@ -343,8 +368,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { if err != nil { return err } - if msg.Size > ProtocolMaxMsgSize { - return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + if msg.Size > protocolMaxMsgSize { + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) } defer msg.Discard() @@ -659,6 +684,9 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } + if err := request.sanityCheck(); err != nil { + return err + } request.Block.ReceivedAt = msg.ReceivedAt request.Block.ReceivedFrom = p diff --git a/vendor/github.com/ethereum/go-ethereum/eth/peer.go b/vendor/github.com/ethereum/go-ethereum/eth/peer.go index 54c0ea0d5..814c787b8 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/peer.go @@ -196,9 +196,13 @@ func (p *peer) MarkTransaction(hash common.Hash) { // SendTransactions sends transactions to the peer and includes the hashes // in its transaction hash set for future reference. func (p *peer) SendTransactions(txs types.Transactions) error { + // Mark all the transactions as known, but ensure we don't overflow our limits for _, tx := range txs { p.knownTxs.Add(tx.Hash()) } + for p.knownTxs.Cardinality() >= maxKnownTxs { + p.knownTxs.Pop() + } return p2p.Send(p.rw, TxMsg, txs) } @@ -207,9 +211,13 @@ func (p *peer) SendTransactions(txs types.Transactions) error { func (p *peer) AsyncSendTransactions(txs []*types.Transaction) { select { case p.queuedTxs <- txs: + // Mark all the transactions as known, but ensure we don't overflow our limits for _, tx := range txs { p.knownTxs.Add(tx.Hash()) } + for p.knownTxs.Cardinality() >= maxKnownTxs { + p.knownTxs.Pop() + } default: p.Log().Debug("Dropping transaction propagation", "count", len(txs)) } @@ -218,9 +226,13 @@ func (p *peer) AsyncSendTransactions(txs []*types.Transaction) { // SendNewBlockHashes announces the availability of a number of blocks through // a hash notification. func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { + // Mark all the block hashes as known, but ensure we don't overflow our limits for _, hash := range hashes { p.knownBlocks.Add(hash) } + for p.knownBlocks.Cardinality() >= maxKnownBlocks { + p.knownBlocks.Pop() + } request := make(newBlockHashesData, len(hashes)) for i := 0; i < len(hashes); i++ { request[i].Hash = hashes[i] @@ -235,7 +247,11 @@ func (p *peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error func (p *peer) AsyncSendNewBlockHash(block *types.Block) { select { case p.queuedAnns <- block: + // Mark all the block hash as known, but ensure we don't overflow our limits p.knownBlocks.Add(block.Hash()) + for p.knownBlocks.Cardinality() >= maxKnownBlocks { + p.knownBlocks.Pop() + } default: p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) } @@ -243,7 +259,11 @@ func (p *peer) AsyncSendNewBlockHash(block *types.Block) { // SendNewBlock propagates an entire block to a remote peer. func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { + // Mark all the block hash as known, but ensure we don't overflow our limits p.knownBlocks.Add(block.Hash()) + for p.knownBlocks.Cardinality() >= maxKnownBlocks { + p.knownBlocks.Pop() + } return p2p.Send(p.rw, NewBlockMsg, []interface{}{block, td}) } @@ -252,7 +272,11 @@ func (p *peer) SendNewBlock(block *types.Block, td *big.Int) error { func (p *peer) AsyncSendNewBlock(block *types.Block, td *big.Int) { select { case p.queuedProps <- &propEvent{block: block, td: td}: + // Mark all the block hash as known, but ensure we don't overflow our limits p.knownBlocks.Add(block.Hash()) + for p.knownBlocks.Cardinality() >= maxKnownBlocks { + p.knownBlocks.Pop() + } default: p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) } @@ -370,8 +394,8 @@ func (p *peer) readStatus(network uint64, status *statusData, genesis common.Has if msg.Code != StatusMsg { return errResp(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg) } - if msg.Size > ProtocolMaxMsgSize { - return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + if msg.Size > protocolMaxMsgSize { + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, protocolMaxMsgSize) } // Decode the handshake and make sure everything matches if err := msg.Decode(&status); err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/eth/protocol.go b/vendor/github.com/ethereum/go-ethereum/eth/protocol.go index 497ba4c59..de0c979d8 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/protocol.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/protocol.go @@ -34,16 +34,16 @@ const ( eth63 = 63 ) -// ProtocolName is the official short name of the protocol used during capability negotiation. -var ProtocolName = "eth" +// protocolName is the official short name of the protocol used during capability negotiation. +const protocolName = "eth" // ProtocolVersions are the supported versions of the eth protocol (first is primary). -var ProtocolVersions = []uint{eth63, eth62} +var ProtocolVersions = []uint{eth63} -// ProtocolLengths are the number of implemented message corresponding to different protocol versions. -var ProtocolLengths = []uint64{17, 8} +// protocolLengths are the number of implemented message corresponding to different protocol versions. +var protocolLengths = map[uint]uint64{eth63: 17, eth62: 8} -const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message +const protocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message // eth protocol message codes const ( @@ -173,6 +173,19 @@ type newBlockData struct { TD *big.Int } +// sanityCheck verifies that the values are reasonable, as a DoS protection +func (request *newBlockData) sanityCheck() error { + if err := request.Block.SanityCheck(); err != nil { + return err + } + //TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times + // larger, it will still fit within 100 bits + if tdlen := request.TD.BitLen(); tdlen > 100 { + return fmt.Errorf("too large block TD: bitlen %d", tdlen) + } + return nil +} + // blockBody represents the data content of a single block. type blockBody struct { Transactions []*types.Transaction // Transactions contained within a block diff --git a/vendor/github.com/ethereum/go-ethereum/eth/sync.go b/vendor/github.com/ethereum/go-ethereum/eth/sync.go index 9cac4fbe8..9e180ee20 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/sync.go @@ -135,6 +135,7 @@ func (pm *ProtocolManager) syncer() { // Start and ensure cleanup of sync mechanisms pm.fetcher.Start() defer pm.fetcher.Stop() + defer pm.downloader.Terminate() // Wait for different events to fire synchronisation operations forceSync := time.NewTicker(forceSyncCycle) @@ -178,14 +179,6 @@ func (pm *ProtocolManager) synchronise(peer *peer) { if atomic.LoadUint32(&pm.fastSync) == 1 { // Fast sync was explicitly requested, and explicitly granted mode = downloader.FastSync - } else if currentBlock.NumberU64() == 0 && pm.blockchain.CurrentFastBlock().NumberU64() > 0 { - // The database seems empty as the current block is the genesis. Yet the fast - // block is ahead, so fast sync was enabled for this node at a certain point. - // The only scenario where this can happen is if the user manually (or via a - // bad block) rolled back a fast sync node below the sync point. In this case - // however it's safe to reenable fast sync. - atomic.StoreUint32(&pm.fastSync, 1) - mode = downloader.FastSync } if mode == downloader.FastSync { // Make sure the peer's total difficulty we are synchronizing is higher. @@ -201,8 +194,17 @@ func (pm *ProtocolManager) synchronise(peer *peer) { log.Info("Fast sync complete, auto disabling") atomic.StoreUint32(&pm.fastSync, 0) } - atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done - if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 { + // If we've successfully finished a sync cycle and passed any required checkpoint, + // enable accepting transactions from the network. + head := pm.blockchain.CurrentBlock() + if head.NumberU64() >= pm.checkpointNumber { + // Checkpoint passed, sanity check the timestamp to have a fallback mechanism + // for non-checkpointed (number = 0) private networks. + if head.Time() >= uint64(time.Now().AddDate(0, -1, 0).Unix()) { + atomic.StoreUint32(&pm.acceptTxs, 1) + } + } + if head.NumberU64() > 0 { // We've completed a sync cycle, notify all peers of new state. This path is // essential in star-topology networks where a gateway node needs to notify // all its out-of-date peers of the availability of a new block. This failure diff --git a/vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/evmdis_tracer.js b/vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/evmdis_tracer.js index 2790e0fd5..bb19777ab 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/evmdis_tracer.js +++ b/vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/evmdis_tracer.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// evmdisTracer returns sufficent information from a trace to perform evmdis-style +// evmdisTracer returns sufficient information from a trace to perform evmdis-style // disassembly. { stack: [{ops: []}], diff --git a/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go b/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go index 9d6701868..c0729fb1d 100644 --- a/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go +++ b/vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go @@ -390,7 +390,7 @@ func New(code string) (*Tracer, error) { return 1 }) tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int { - _, ok := vm.PrecompiledContractsByzantium[common.BytesToAddress(popSlice(ctx))] + _, ok := vm.PrecompiledContractsIstanbul[common.BytesToAddress(popSlice(ctx))] ctx.PushBoolean(ok) return 1 }) diff --git a/vendor/github.com/ethereum/go-ethereum/eth/ulc_config.go b/vendor/github.com/ethereum/go-ethereum/eth/ulc_config.go deleted file mode 100644 index 960cb0da5..000000000 --- a/vendor/github.com/ethereum/go-ethereum/eth/ulc_config.go +++ /dev/null @@ -1,9 +0,0 @@ -package eth - -const DefaultUTCMinTrustedFraction = 75 - -// ULCConfig is a Ultra Light client options. -type ULCConfig struct { - TrustedServers []string `toml:",omitempty"` // A list of trusted servers - MinTrustedFraction int `toml:",omitempty"` // Minimum percentage of connected trusted servers to validate trusted (1-100) -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go b/vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go index f3163e19b..0a6f73ab5 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go +++ b/vendor/github.com/ethereum/go-ethereum/ethclient/ethclient.go @@ -61,6 +61,16 @@ func (ec *Client) Close() { // Blockchain Access +// ChainId retrieves the current chain ID for transaction replay protection. +func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { + var result hexutil.Big + err := ec.c.CallContext(ctx, &result, "eth_chainId") + if err != nil { + return nil, err + } + return (*big.Int)(&result), err +} + // BlockByHash returns the given full block. // // Note that loading full blocks requires two requests. Use HeaderByHash @@ -241,12 +251,13 @@ func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) ( func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { var json *rpcTransaction err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) - if err == nil { - if json == nil { - return nil, ethereum.NotFound - } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { - return nil, fmt.Errorf("server returned transaction without signature") - } + if err != nil { + return nil, err + } + if json == nil { + return nil, ethereum.NotFound + } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { + return nil, fmt.Errorf("server returned transaction without signature") } if json.From != nil && json.BlockHash != nil { setSenderFromServer(json.tx, *json.From, *json.BlockHash) diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/.gitignore b/vendor/github.com/ethereum/go-ethereum/ethdb/.gitignore deleted file mode 100644 index f725d58d1..000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile ~/.gitignore_global - -/tmp -*/**/*un~ -*un~ -.DS_Store -*/**/.DS_Store - diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/interface.go b/vendor/github.com/ethereum/go-ethereum/ethdb/batch.go similarity index 53% rename from vendor/github.com/ethereum/go-ethereum/ethdb/interface.go rename to vendor/github.com/ethereum/go-ethereum/ethdb/batch.go index af1355779..e261415bf 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/interface.go +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/batch.go @@ -1,4 +1,4 @@ -// Copyright 2014 The go-ethereum Authors +// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -16,37 +16,31 @@ package ethdb -// Code using batches should try to add this much data to the batch. -// The value was determined empirically. +// IdealBatchSize defines the size of the data batches should ideally add in one +// write. const IdealBatchSize = 100 * 1024 -// Putter wraps the database write operation supported by both batches and regular databases. -type Putter interface { - Put(key []byte, value []byte) error +// Batch is a write-only database that commits changes to its host database +// when Write is called. A batch cannot be used concurrently. +type Batch interface { + KeyValueWriter + + // ValueSize retrieves the amount of data queued up for writing. + ValueSize() int + + // Write flushes any accumulated data to disk. + Write() error + + // Reset resets the batch for reuse. + Reset() + + // Replay replays the batch contents. + Replay(w KeyValueWriter) error } -// Deleter wraps the database delete operation supported by both batches and regular databases. -type Deleter interface { - Delete(key []byte) error -} - -// Database wraps all database operations. All methods are safe for concurrent use. -type Database interface { - Putter - Deleter - Get(key []byte) ([]byte, error) - Has(key []byte) (bool, error) - Close() +// Batcher wraps the NewBatch method of a backing data store. +type Batcher interface { + // NewBatch creates a write-only database that buffers changes to its host db + // until a final write is called. NewBatch() Batch } - -// Batch is a write-only database that commits changes to its host database -// when Write is called. Batch cannot be used concurrently. -type Batch interface { - Putter - Deleter - ValueSize() int // amount of data in the batch - Write() error - // Reset resets the batch for reuse - Reset() -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go index 6c62d6a38..0dc14624b 100644 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/database.go +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/database.go @@ -14,371 +14,118 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// +build !js - +// Package ethdb defines the interfaces for an Ethereum data store. package ethdb -import ( - "fmt" - "strconv" - "strings" - "sync" - "time" +import "io" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" -) +// KeyValueReader wraps the Has and Get method of a backing data store. +type KeyValueReader interface { + // Has retrieves if a key is present in the key-value data store. + Has(key []byte) (bool, error) -const ( - writePauseWarningThrottler = 1 * time.Minute -) - -var OpenFileLimit = 64 - -type LDBDatabase struct { - fn string // filename for reporting - db *leveldb.DB // LevelDB instance - - compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written - - quitLock sync.Mutex // Mutex protecting the quit channel access - quitChan chan chan error // Quit channel to stop the metrics collection before closing the database - - log log.Logger // Contextual logger tracking the database path + // Get retrieves the given key if it's present in the key-value data store. + Get(key []byte) ([]byte, error) } -// NewLDBDatabase returns a LevelDB wrapped object. -func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { - logger := log.New("database", file) +// KeyValueWriter wraps the Put method of a backing data store. +type KeyValueWriter interface { + // Put inserts the given value into the key-value data store. + Put(key []byte, value []byte) error - // Ensure we have some minimal caching and file guarantees - if cache < 16 { - cache = 16 - } - if handles < 16 { - handles = 16 - } - logger.Info("Allocated cache and file handles", "cache", cache, "handles", handles) - - // Open the db and recover any potential corruptions - db, err := leveldb.OpenFile(file, &opt.Options{ - OpenFilesCacheCapacity: handles, - BlockCacheCapacity: cache / 2 * opt.MiB, - WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally - Filter: filter.NewBloomFilter(10), - }) - if _, corrupted := err.(*errors.ErrCorrupted); corrupted { - db, err = leveldb.RecoverFile(file, nil) - } - // (Re)check for errors and abort if opening of the db failed - if err != nil { - return nil, err - } - return &LDBDatabase{ - fn: file, - db: db, - log: logger, - }, nil + // Delete removes the key from the key-value data store. + Delete(key []byte) error } -// Path returns the path to the database directory. -func (db *LDBDatabase) Path() string { - return db.fn +// Stater wraps the Stat method of a backing data store. +type Stater interface { + // Stat returns a particular internal stat of the database. + Stat(property string) (string, error) } -// Put puts the given key / value to the queue -func (db *LDBDatabase) Put(key []byte, value []byte) error { - return db.db.Put(key, value, nil) +// Compacter wraps the Compact method of a backing data store. +type Compacter interface { + // Compact flattens the underlying data store for the given key range. In essence, + // deleted and overwritten versions are discarded, and the data is rearranged to + // reduce the cost of operations needed to access them. + // + // A nil start is treated as a key before all keys in the data store; a nil limit + // is treated as a key after all keys in the data store. If both is nil then it + // will compact entire data store. + Compact(start []byte, limit []byte) error } -func (db *LDBDatabase) Has(key []byte) (bool, error) { - return db.db.Has(key, nil) +// KeyValueStore contains all the methods required to allow handling different +// key-value data stores backing the high level database. +type KeyValueStore interface { + KeyValueReader + KeyValueWriter + Batcher + Iteratee + Stater + Compacter + io.Closer } -// Get returns the given key if it's present. -func (db *LDBDatabase) Get(key []byte) ([]byte, error) { - dat, err := db.db.Get(key, nil) - if err != nil { - return nil, err - } - return dat, nil +// AncientReader contains the methods required to read from immutable ancient data. +type AncientReader interface { + // HasAncient returns an indicator whether the specified data exists in the + // ancient store. + HasAncient(kind string, number uint64) (bool, error) + + // Ancient retrieves an ancient binary blob from the append-only immutable files. + Ancient(kind string, number uint64) ([]byte, error) + + // Ancients returns the ancient item numbers in the ancient store. + Ancients() (uint64, error) + + // AncientSize returns the ancient size of the specified category. + AncientSize(kind string) (uint64, error) } -// Delete deletes the key from the queue and database -func (db *LDBDatabase) Delete(key []byte) error { - return db.db.Delete(key, nil) +// AncientWriter contains the methods required to write to immutable ancient data. +type AncientWriter interface { + // AppendAncient injects all binary blobs belong to block at the end of the + // append-only immutable table files. + AppendAncient(number uint64, hash, header, body, receipt, td []byte) error + + // TruncateAncients discards all but the first n ancient data from the ancient store. + TruncateAncients(n uint64) error + + // Sync flushes all in-memory ancient store data to disk. + Sync() error } -func (db *LDBDatabase) NewIterator() iterator.Iterator { - return db.db.NewIterator(nil, nil) +// Reader contains the methods required to read data from both key-value as well as +// immutable ancient data. +type Reader interface { + KeyValueReader + AncientReader } -// NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix. -func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator { - return db.db.NewIterator(util.BytesPrefix(prefix), nil) +// Writer contains the methods required to write data to both key-value as well as +// immutable ancient data. +type Writer interface { + KeyValueWriter + AncientWriter } -func (db *LDBDatabase) Close() { - // Stop the metrics collection to avoid internal database races - db.quitLock.Lock() - defer db.quitLock.Unlock() - - if db.quitChan != nil { - errc := make(chan error) - db.quitChan <- errc - if err := <-errc; err != nil { - db.log.Error("Metrics collection failed", "err", err) - } - db.quitChan = nil - } - err := db.db.Close() - if err == nil { - db.log.Info("Database closed") - } else { - db.log.Error("Failed to close database", "err", err) - } +// AncientStore contains all the methods required to allow handling different +// ancient data stores backing immutable chain data store. +type AncientStore interface { + AncientReader + AncientWriter + io.Closer } -func (db *LDBDatabase) LDB() *leveldb.DB { - return db.db -} - -// Meter configures the database metrics collectors and -func (db *LDBDatabase) Meter(prefix string) { - // Initialize all the metrics collector at the requested prefix - db.compTimeMeter = metrics.NewRegisteredMeter(prefix+"compact/time", nil) - db.compReadMeter = metrics.NewRegisteredMeter(prefix+"compact/input", nil) - db.compWriteMeter = metrics.NewRegisteredMeter(prefix+"compact/output", nil) - db.diskReadMeter = metrics.NewRegisteredMeter(prefix+"disk/read", nil) - db.diskWriteMeter = metrics.NewRegisteredMeter(prefix+"disk/write", nil) - db.writeDelayMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/duration", nil) - db.writeDelayNMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/counter", nil) - - // Create a quit channel for the periodic collector and run it - db.quitLock.Lock() - db.quitChan = make(chan chan error) - db.quitLock.Unlock() - - go db.meter(3 * time.Second) -} - -// meter periodically retrieves internal leveldb counters and reports them to -// the metrics subsystem. -// -// This is how a stats table look like (currently): -// Compactions -// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) -// -------+------------+---------------+---------------+---------------+--------------- -// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 -// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 -// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 -// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 -// -// This is how the write delay look like (currently): -// DelayN:5 Delay:406.604657ms Paused: false -// -// This is how the iostats look like (currently): -// Read(MB):3895.04860 Write(MB):3654.64712 -func (db *LDBDatabase) meter(refresh time.Duration) { - // Create the counters to store current and previous compaction values - compactions := make([][]float64, 2) - for i := 0; i < 2; i++ { - compactions[i] = make([]float64, 3) - } - // Create storage for iostats. - var iostats [2]float64 - - // Create storage and warning log tracer for write delay. - var ( - delaystats [2]int64 - lastWritePaused time.Time - ) - - var ( - errc chan error - merr error - ) - - // Iterate ad infinitum and collect the stats - for i := 1; errc == nil && merr == nil; i++ { - // Retrieve the database stats - stats, err := db.db.GetProperty("leveldb.stats") - if err != nil { - db.log.Error("Failed to read database stats", "err", err) - merr = err - continue - } - // Find the compaction table, skip the header - lines := strings.Split(stats, "\n") - for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" { - lines = lines[1:] - } - if len(lines) <= 3 { - db.log.Error("Compaction table not found") - merr = errors.New("compaction table not found") - continue - } - lines = lines[3:] - - // Iterate over all the table rows, and accumulate the entries - for j := 0; j < len(compactions[i%2]); j++ { - compactions[i%2][j] = 0 - } - for _, line := range lines { - parts := strings.Split(line, "|") - if len(parts) != 6 { - break - } - for idx, counter := range parts[3:] { - value, err := strconv.ParseFloat(strings.TrimSpace(counter), 64) - if err != nil { - db.log.Error("Compaction entry parsing failed", "err", err) - merr = err - continue - } - compactions[i%2][idx] += value - } - } - // Update all the requested meters - if db.compTimeMeter != nil { - db.compTimeMeter.Mark(int64((compactions[i%2][0] - compactions[(i-1)%2][0]) * 1000 * 1000 * 1000)) - } - if db.compReadMeter != nil { - db.compReadMeter.Mark(int64((compactions[i%2][1] - compactions[(i-1)%2][1]) * 1024 * 1024)) - } - if db.compWriteMeter != nil { - db.compWriteMeter.Mark(int64((compactions[i%2][2] - compactions[(i-1)%2][2]) * 1024 * 1024)) - } - - // Retrieve the write delay statistic - writedelay, err := db.db.GetProperty("leveldb.writedelay") - if err != nil { - db.log.Error("Failed to read database write delay statistic", "err", err) - merr = err - continue - } - var ( - delayN int64 - delayDuration string - duration time.Duration - paused bool - ) - if n, err := fmt.Sscanf(writedelay, "DelayN:%d Delay:%s Paused:%t", &delayN, &delayDuration, &paused); n != 3 || err != nil { - db.log.Error("Write delay statistic not found") - merr = err - continue - } - duration, err = time.ParseDuration(delayDuration) - if err != nil { - db.log.Error("Failed to parse delay duration", "err", err) - merr = err - continue - } - if db.writeDelayNMeter != nil { - db.writeDelayNMeter.Mark(delayN - delaystats[0]) - } - if db.writeDelayMeter != nil { - db.writeDelayMeter.Mark(duration.Nanoseconds() - delaystats[1]) - } - // If a warning that db is performing compaction has been displayed, any subsequent - // warnings will be withheld for one minute not to overwhelm the user. - if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && - time.Now().After(lastWritePaused.Add(writePauseWarningThrottler)) { - db.log.Warn("Database compacting, degraded performance") - lastWritePaused = time.Now() - } - delaystats[0], delaystats[1] = delayN, duration.Nanoseconds() - - // Retrieve the database iostats. - ioStats, err := db.db.GetProperty("leveldb.iostats") - if err != nil { - db.log.Error("Failed to read database iostats", "err", err) - merr = err - continue - } - var nRead, nWrite float64 - parts := strings.Split(ioStats, " ") - if len(parts) < 2 { - db.log.Error("Bad syntax of ioStats", "ioStats", ioStats) - merr = fmt.Errorf("bad syntax of ioStats %s", ioStats) - continue - } - if n, err := fmt.Sscanf(parts[0], "Read(MB):%f", &nRead); n != 1 || err != nil { - db.log.Error("Bad syntax of read entry", "entry", parts[0]) - merr = err - continue - } - if n, err := fmt.Sscanf(parts[1], "Write(MB):%f", &nWrite); n != 1 || err != nil { - db.log.Error("Bad syntax of write entry", "entry", parts[1]) - merr = err - continue - } - if db.diskReadMeter != nil { - db.diskReadMeter.Mark(int64((nRead - iostats[0]) * 1024 * 1024)) - } - if db.diskWriteMeter != nil { - db.diskWriteMeter.Mark(int64((nWrite - iostats[1]) * 1024 * 1024)) - } - iostats[0], iostats[1] = nRead, nWrite - - // Sleep a bit, then repeat the stats collection - select { - case errc = <-db.quitChan: - // Quit requesting, stop hammering the database - case <-time.After(refresh): - // Timeout, gather a new set of stats - } - } - - if errc == nil { - errc = <-db.quitChan - } - errc <- merr -} - -func (db *LDBDatabase) NewBatch() Batch { - return &ldbBatch{db: db.db, b: new(leveldb.Batch)} -} - -type ldbBatch struct { - db *leveldb.DB - b *leveldb.Batch - size int -} - -func (b *ldbBatch) Put(key, value []byte) error { - b.b.Put(key, value) - b.size += len(value) - return nil -} - -func (b *ldbBatch) Delete(key []byte) error { - b.b.Delete(key) - b.size += 1 - return nil -} - -func (b *ldbBatch) Write() error { - return b.db.Write(b.b, nil) -} - -func (b *ldbBatch) ValueSize() int { - return b.size -} - -func (b *ldbBatch) Reset() { - b.b.Reset() - b.size = 0 +// Database contains all the methods required by the high level database to not +// only access the key-value data store but also the chain freezer. +type Database interface { + Reader + Writer + Batcher + Iteratee + Stater + Compacter + io.Closer } diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go b/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go deleted file mode 100644 index ba6eeb5a2..000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/database_js.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 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 . - -// +build js - -package ethdb - -import ( - "errors" -) - -var errNotSupported = errors.New("ethdb: not supported") - -type LDBDatabase struct { -} - -// NewLDBDatabase returns a LevelDB wrapped object. -func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { - return nil, errNotSupported -} - -// Path returns the path to the database directory. -func (db *LDBDatabase) Path() string { - return "" -} - -// Put puts the given key / value to the queue -func (db *LDBDatabase) Put(key []byte, value []byte) error { - return errNotSupported -} - -func (db *LDBDatabase) Has(key []byte) (bool, error) { - return false, errNotSupported -} - -// Get returns the given key if it's present. -func (db *LDBDatabase) Get(key []byte) ([]byte, error) { - return nil, errNotSupported -} - -// Delete deletes the key from the queue and database -func (db *LDBDatabase) Delete(key []byte) error { - return errNotSupported -} - -func (db *LDBDatabase) Close() { -} - -// Meter configures the database metrics collectors and -func (db *LDBDatabase) Meter(prefix string) { -} - -func (db *LDBDatabase) NewBatch() Batch { - return nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go b/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go new file mode 100644 index 000000000..419e9bdfc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/iterator.go @@ -0,0 +1,66 @@ +// 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 ethdb + +// Iterator iterates over a database's key/value pairs in ascending key order. +// +// When it encounters an error any seek will return false and will yield no key/ +// value pairs. The error can be queried by calling the Error method. Calling +// Release is still necessary. +// +// An iterator must be released after use, but it is not necessary to read an +// iterator until exhaustion. An iterator is not safe for concurrent use, but it +// is safe to use multiple iterators concurrently. +type Iterator interface { + // Next moves the iterator to the next key/value pair. It returns whether the + // iterator is exhausted. + Next() bool + + // Error returns any accumulated error. Exhausting all the key/value pairs + // is not considered to be an error. + Error() error + + // Key returns the key of the current key/value pair, or nil if done. The caller + // should not modify the contents of the returned slice, and its contents may + // change on the next call to Next. + Key() []byte + + // Value returns the value of the current key/value pair, or nil if done. The + // caller should not modify the contents of the returned slice, and its contents + // may change on the next call to Next. + Value() []byte + + // Release releases associated resources. Release should always succeed and can + // be called multiple times without causing error. + Release() +} + +// Iteratee wraps the NewIterator methods of a backing data store. +type Iteratee interface { + // NewIterator creates a binary-alphabetical iterator over the entire keyspace + // contained within the key-value database. + NewIterator() Iterator + + // NewIteratorWithStart creates a binary-alphabetical iterator over a subset of + // database content starting at a particular initial key (or after, if it does + // not exist). + NewIteratorWithStart(start []byte) Iterator + + // NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset + // of database content with a particular key prefix. + NewIteratorWithPrefix(prefix []byte) Iterator +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go new file mode 100644 index 000000000..aba6593c7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/leveldb/leveldb.go @@ -0,0 +1,458 @@ +// 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 . + +// +build !js + +// Package leveldb implements the key-value database layer based on LevelDB. +package leveldb + +import ( + "fmt" + "strconv" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/syndtr/goleveldb/leveldb/filter" + "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/util" +) + +const ( + // degradationWarnInterval specifies how often warning should be printed if the + // leveldb database cannot keep up with requested writes. + degradationWarnInterval = time.Minute + + // minCache is the minimum amount of memory in megabytes to allocate to leveldb + // read and write caching, split half and half. + minCache = 16 + + // minHandles is the minimum number of files handles to allocate to the open + // database files. + minHandles = 16 + + // metricsGatheringInterval specifies the interval to retrieve leveldb database + // compaction, io and pause stats to report to the user. + metricsGatheringInterval = 3 * time.Second +) + +// Database is a persistent key-value store. Apart from basic data storage +// functionality it also supports batch writes and iterating over the keyspace in +// binary-alphabetical order. +type Database struct { + fn string // filename for reporting + db *leveldb.DB // LevelDB instance + + compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction + compReadMeter metrics.Meter // Meter for measuring the data read during compaction + compWriteMeter metrics.Meter // Meter for measuring the data written during compaction + writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction + writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction + diskSizeGauge metrics.Gauge // Gauge for tracking the size of all the levels in the database + diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read + diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written + + quitLock sync.Mutex // Mutex protecting the quit channel access + quitChan chan chan error // Quit channel to stop the metrics collection before closing the database + + log log.Logger // Contextual logger tracking the database path +} + +// New returns a wrapped LevelDB object. The namespace is the prefix that the +// metrics reporting should use for surfacing internal stats. +func New(file string, cache int, handles int, namespace string) (*Database, error) { + // Ensure we have some minimal caching and file guarantees + if cache < minCache { + cache = minCache + } + if handles < minHandles { + handles = minHandles + } + logger := log.New("database", file) + logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles) + + // Open the db and recover any potential corruptions + db, err := leveldb.OpenFile(file, &opt.Options{ + OpenFilesCacheCapacity: handles, + BlockCacheCapacity: cache / 2 * opt.MiB, + WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally + Filter: filter.NewBloomFilter(10), + }) + if _, corrupted := err.(*errors.ErrCorrupted); corrupted { + db, err = leveldb.RecoverFile(file, nil) + } + if err != nil { + return nil, err + } + // Assemble the wrapper with all the registered metrics + ldb := &Database{ + fn: file, + db: db, + log: logger, + quitChan: make(chan chan error), + } + ldb.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil) + ldb.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil) + ldb.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil) + ldb.diskSizeGauge = metrics.NewRegisteredGauge(namespace+"disk/size", nil) + ldb.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil) + ldb.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil) + ldb.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil) + ldb.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil) + + // Start up the metrics gathering and return + go ldb.meter(metricsGatheringInterval) + return ldb, nil +} + +// Close stops the metrics collection, flushes any pending data to disk and closes +// all io accesses to the underlying key-value store. +func (db *Database) Close() error { + db.quitLock.Lock() + defer db.quitLock.Unlock() + + if db.quitChan != nil { + errc := make(chan error) + db.quitChan <- errc + if err := <-errc; err != nil { + db.log.Error("Metrics collection failed", "err", err) + } + db.quitChan = nil + } + return db.db.Close() +} + +// Has retrieves if a key is present in the key-value store. +func (db *Database) Has(key []byte) (bool, error) { + return db.db.Has(key, nil) +} + +// Get retrieves the given key if it's present in the key-value store. +func (db *Database) Get(key []byte) ([]byte, error) { + dat, err := db.db.Get(key, nil) + if err != nil { + return nil, err + } + return dat, nil +} + +// Put inserts the given value into the key-value store. +func (db *Database) Put(key []byte, value []byte) error { + return db.db.Put(key, value, nil) +} + +// Delete removes the key from the key-value store. +func (db *Database) Delete(key []byte) error { + return db.db.Delete(key, nil) +} + +// NewBatch creates a write-only key-value store that buffers changes to its host +// database until a final write is called. +func (db *Database) NewBatch() ethdb.Batch { + return &batch{ + db: db.db, + b: new(leveldb.Batch), + } +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the leveldb database. +func (db *Database) NewIterator() ethdb.Iterator { + return db.db.NewIterator(new(util.Range), nil) +} + +// NewIteratorWithStart creates a binary-alphabetical iterator over a subset of +// database content starting at a particular initial key (or after, if it does +// not exist). +func (db *Database) NewIteratorWithStart(start []byte) ethdb.Iterator { + return db.db.NewIterator(&util.Range{Start: start}, nil) +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (db *Database) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + return db.db.NewIterator(util.BytesPrefix(prefix), nil) +} + +// Stat returns a particular internal stat of the database. +func (db *Database) Stat(property string) (string, error) { + return db.db.GetProperty(property) +} + +// Compact flattens the underlying data store for the given key range. In essence, +// deleted and overwritten versions are discarded, and the data is rearranged to +// reduce the cost of operations needed to access them. +// +// A nil start is treated as a key before all keys in the data store; a nil limit +// is treated as a key after all keys in the data store. If both is nil then it +// will compact entire data store. +func (db *Database) Compact(start []byte, limit []byte) error { + return db.db.CompactRange(util.Range{Start: start, Limit: limit}) +} + +// Path returns the path to the database directory. +func (db *Database) Path() string { + return db.fn +} + +// meter periodically retrieves internal leveldb counters and reports them to +// the metrics subsystem. +// +// This is how a LevelDB stats table looks like (currently): +// Compactions +// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) +// -------+------------+---------------+---------------+---------------+--------------- +// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 +// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 +// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 +// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 +// +// This is how the write delay look like (currently): +// DelayN:5 Delay:406.604657ms Paused: false +// +// This is how the iostats look like (currently): +// Read(MB):3895.04860 Write(MB):3654.64712 +func (db *Database) meter(refresh time.Duration) { + // Create the counters to store current and previous compaction values + compactions := make([][]float64, 2) + for i := 0; i < 2; i++ { + compactions[i] = make([]float64, 4) + } + // Create storage for iostats. + var iostats [2]float64 + + // Create storage and warning log tracer for write delay. + var ( + delaystats [2]int64 + lastWritePaused time.Time + ) + + var ( + errc chan error + merr error + ) + + // Iterate ad infinitum and collect the stats + for i := 1; errc == nil && merr == nil; i++ { + // Retrieve the database stats + stats, err := db.db.GetProperty("leveldb.stats") + if err != nil { + db.log.Error("Failed to read database stats", "err", err) + merr = err + continue + } + // Find the compaction table, skip the header + lines := strings.Split(stats, "\n") + for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" { + lines = lines[1:] + } + if len(lines) <= 3 { + db.log.Error("Compaction leveldbTable not found") + merr = errors.New("compaction leveldbTable not found") + continue + } + lines = lines[3:] + + // Iterate over all the leveldbTable rows, and accumulate the entries + for j := 0; j < len(compactions[i%2]); j++ { + compactions[i%2][j] = 0 + } + for _, line := range lines { + parts := strings.Split(line, "|") + if len(parts) != 6 { + break + } + for idx, counter := range parts[2:] { + value, err := strconv.ParseFloat(strings.TrimSpace(counter), 64) + if err != nil { + db.log.Error("Compaction entry parsing failed", "err", err) + merr = err + continue + } + compactions[i%2][idx] += value + } + } + // Update all the requested meters + if db.diskSizeGauge != nil { + db.diskSizeGauge.Update(int64(compactions[i%2][0] * 1024 * 1024)) + } + if db.compTimeMeter != nil { + db.compTimeMeter.Mark(int64((compactions[i%2][1] - compactions[(i-1)%2][1]) * 1000 * 1000 * 1000)) + } + if db.compReadMeter != nil { + db.compReadMeter.Mark(int64((compactions[i%2][2] - compactions[(i-1)%2][2]) * 1024 * 1024)) + } + if db.compWriteMeter != nil { + db.compWriteMeter.Mark(int64((compactions[i%2][3] - compactions[(i-1)%2][3]) * 1024 * 1024)) + } + // Retrieve the write delay statistic + writedelay, err := db.db.GetProperty("leveldb.writedelay") + if err != nil { + db.log.Error("Failed to read database write delay statistic", "err", err) + merr = err + continue + } + var ( + delayN int64 + delayDuration string + duration time.Duration + paused bool + ) + if n, err := fmt.Sscanf(writedelay, "DelayN:%d Delay:%s Paused:%t", &delayN, &delayDuration, &paused); n != 3 || err != nil { + db.log.Error("Write delay statistic not found") + merr = err + continue + } + duration, err = time.ParseDuration(delayDuration) + if err != nil { + db.log.Error("Failed to parse delay duration", "err", err) + merr = err + continue + } + if db.writeDelayNMeter != nil { + db.writeDelayNMeter.Mark(delayN - delaystats[0]) + } + if db.writeDelayMeter != nil { + db.writeDelayMeter.Mark(duration.Nanoseconds() - delaystats[1]) + } + // If a warning that db is performing compaction has been displayed, any subsequent + // warnings will be withheld for one minute not to overwhelm the user. + if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && + time.Now().After(lastWritePaused.Add(degradationWarnInterval)) { + db.log.Warn("Database compacting, degraded performance") + lastWritePaused = time.Now() + } + delaystats[0], delaystats[1] = delayN, duration.Nanoseconds() + + // Retrieve the database iostats. + ioStats, err := db.db.GetProperty("leveldb.iostats") + if err != nil { + db.log.Error("Failed to read database iostats", "err", err) + merr = err + continue + } + var nRead, nWrite float64 + parts := strings.Split(ioStats, " ") + if len(parts) < 2 { + db.log.Error("Bad syntax of ioStats", "ioStats", ioStats) + merr = fmt.Errorf("bad syntax of ioStats %s", ioStats) + continue + } + if n, err := fmt.Sscanf(parts[0], "Read(MB):%f", &nRead); n != 1 || err != nil { + db.log.Error("Bad syntax of read entry", "entry", parts[0]) + merr = err + continue + } + if n, err := fmt.Sscanf(parts[1], "Write(MB):%f", &nWrite); n != 1 || err != nil { + db.log.Error("Bad syntax of write entry", "entry", parts[1]) + merr = err + continue + } + if db.diskReadMeter != nil { + db.diskReadMeter.Mark(int64((nRead - iostats[0]) * 1024 * 1024)) + } + if db.diskWriteMeter != nil { + db.diskWriteMeter.Mark(int64((nWrite - iostats[1]) * 1024 * 1024)) + } + iostats[0], iostats[1] = nRead, nWrite + + // Sleep a bit, then repeat the stats collection + select { + case errc = <-db.quitChan: + // Quit requesting, stop hammering the database + case <-time.After(refresh): + // Timeout, gather a new set of stats + } + } + + if errc == nil { + errc = <-db.quitChan + } + errc <- merr +} + +// batch is a write-only leveldb batch that commits changes to its host database +// when Write is called. A batch cannot be used concurrently. +type batch struct { + db *leveldb.DB + b *leveldb.Batch + size int +} + +// Put inserts the given value into the batch for later committing. +func (b *batch) Put(key, value []byte) error { + b.b.Put(key, value) + b.size += len(value) + return nil +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *batch) Delete(key []byte) error { + b.b.Delete(key) + b.size++ + return nil +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *batch) ValueSize() int { + return b.size +} + +// Write flushes any accumulated data to disk. +func (b *batch) Write() error { + return b.db.Write(b.b, nil) +} + +// Reset resets the batch for reuse. +func (b *batch) Reset() { + b.b.Reset() + b.size = 0 +} + +// Replay replays the batch contents. +func (b *batch) Replay(w ethdb.KeyValueWriter) error { + return b.b.Replay(&replayer{writer: w}) +} + +// replayer is a small wrapper to implement the correct replay methods. +type replayer struct { + writer ethdb.KeyValueWriter + failure error +} + +// Put inserts the given value into the key-value data store. +func (r *replayer) Put(key, value []byte) { + // If the replay already failed, stop executing ops + if r.failure != nil { + return + } + r.failure = r.writer.Put(key, value) +} + +// Delete removes the key from the key-value data store. +func (r *replayer) Delete(key []byte) { + // If the replay already failed, stop executing ops + if r.failure != nil { + return + } + r.failure = r.writer.Delete(key) +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go b/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go deleted file mode 100644 index 727f2f7ca..000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/memory_database.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 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 ethdb - -import ( - "errors" - "sync" - - "github.com/ethereum/go-ethereum/common" -) - -/* - * This is a test memory database. Do not use for any production it does not get persisted - */ -type MemDatabase struct { - db map[string][]byte - lock sync.RWMutex -} - -func NewMemDatabase() *MemDatabase { - return &MemDatabase{ - db: make(map[string][]byte), - } -} - -func NewMemDatabaseWithCap(size int) *MemDatabase { - return &MemDatabase{ - db: make(map[string][]byte, size), - } -} - -func (db *MemDatabase) Put(key []byte, value []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - db.db[string(key)] = common.CopyBytes(value) - return nil -} - -func (db *MemDatabase) Has(key []byte) (bool, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - _, ok := db.db[string(key)] - return ok, nil -} - -func (db *MemDatabase) Get(key []byte) ([]byte, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - if entry, ok := db.db[string(key)]; ok { - return common.CopyBytes(entry), nil - } - return nil, errors.New("not found") -} - -func (db *MemDatabase) Keys() [][]byte { - db.lock.RLock() - defer db.lock.RUnlock() - - keys := [][]byte{} - for key := range db.db { - keys = append(keys, []byte(key)) - } - return keys -} - -func (db *MemDatabase) Delete(key []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - delete(db.db, string(key)) - return nil -} - -func (db *MemDatabase) Close() {} - -func (db *MemDatabase) NewBatch() Batch { - return &memBatch{db: db} -} - -func (db *MemDatabase) Len() int { return len(db.db) } - -type kv struct { - k, v []byte - del bool -} - -type memBatch struct { - db *MemDatabase - writes []kv - size int -} - -func (b *memBatch) Put(key, value []byte) error { - b.writes = append(b.writes, kv{common.CopyBytes(key), common.CopyBytes(value), false}) - b.size += len(value) - return nil -} - -func (b *memBatch) Delete(key []byte) error { - b.writes = append(b.writes, kv{common.CopyBytes(key), nil, true}) - b.size += 1 - return nil -} - -func (b *memBatch) Write() error { - b.db.lock.Lock() - defer b.db.lock.Unlock() - - for _, kv := range b.writes { - if kv.del { - delete(b.db.db, string(kv.k)) - continue - } - b.db.db[string(kv.k)] = kv.v - } - return nil -} - -func (b *memBatch) ValueSize() int { - return b.size -} - -func (b *memBatch) Reset() { - b.writes = b.writes[:0] - b.size = 0 -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go b/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go new file mode 100644 index 000000000..346edc438 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/ethdb/memorydb/memorydb.go @@ -0,0 +1,344 @@ +// 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 memorydb implements the key-value database layer based on memory maps. +package memorydb + +import ( + "errors" + "sort" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" +) + +var ( + // errMemorydbClosed is returned if a memory database was already closed at the + // invocation of a data access operation. + errMemorydbClosed = errors.New("database closed") + + // errMemorydbNotFound is returned if a key is requested that is not found in + // the provided memory database. + errMemorydbNotFound = errors.New("not found") +) + +// Database is an ephemeral key-value store. Apart from basic data storage +// functionality it also supports batch writes and iterating over the keyspace in +// binary-alphabetical order. +type Database struct { + db map[string][]byte + lock sync.RWMutex +} + +// New returns a wrapped map with all the required database interface methods +// implemented. +func New() *Database { + return &Database{ + db: make(map[string][]byte), + } +} + +// NewWithCap returns a wrapped map pre-allocated to the provided capcity with +// all the required database interface methods implemented. +func NewWithCap(size int) *Database { + return &Database{ + db: make(map[string][]byte, size), + } +} + +// Close deallocates the internal map and ensures any consecutive data access op +// failes with an error. +func (db *Database) Close() error { + db.lock.Lock() + defer db.lock.Unlock() + + db.db = nil + return nil +} + +// Has retrieves if a key is present in the key-value store. +func (db *Database) Has(key []byte) (bool, error) { + db.lock.RLock() + defer db.lock.RUnlock() + + if db.db == nil { + return false, errMemorydbClosed + } + _, ok := db.db[string(key)] + return ok, nil +} + +// Get retrieves the given key if it's present in the key-value store. +func (db *Database) Get(key []byte) ([]byte, error) { + db.lock.RLock() + defer db.lock.RUnlock() + + if db.db == nil { + return nil, errMemorydbClosed + } + if entry, ok := db.db[string(key)]; ok { + return common.CopyBytes(entry), nil + } + return nil, errMemorydbNotFound +} + +// Put inserts the given value into the key-value store. +func (db *Database) Put(key []byte, value []byte) error { + db.lock.Lock() + defer db.lock.Unlock() + + if db.db == nil { + return errMemorydbClosed + } + db.db[string(key)] = common.CopyBytes(value) + return nil +} + +// Delete removes the key from the key-value store. +func (db *Database) Delete(key []byte) error { + db.lock.Lock() + defer db.lock.Unlock() + + if db.db == nil { + return errMemorydbClosed + } + delete(db.db, string(key)) + return nil +} + +// NewBatch creates a write-only key-value store that buffers changes to its host +// database until a final write is called. +func (db *Database) NewBatch() ethdb.Batch { + return &batch{ + db: db, + } +} + +// NewIterator creates a binary-alphabetical iterator over the entire keyspace +// contained within the memory database. +func (db *Database) NewIterator() ethdb.Iterator { + return db.NewIteratorWithStart(nil) +} + +// NewIteratorWithStart creates a binary-alphabetical iterator over a subset of +// database content starting at a particular initial key (or after, if it does +// not exist). +func (db *Database) NewIteratorWithStart(start []byte) ethdb.Iterator { + db.lock.RLock() + defer db.lock.RUnlock() + + var ( + st = string(start) + keys = make([]string, 0, len(db.db)) + values = make([][]byte, 0, len(db.db)) + ) + // Collect the keys from the memory database corresponding to the given start + for key := range db.db { + if key >= st { + keys = append(keys, key) + } + } + // Sort the items and retrieve the associated values + sort.Strings(keys) + for _, key := range keys { + values = append(values, db.db[key]) + } + return &iterator{ + keys: keys, + values: values, + } +} + +// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset +// of database content with a particular key prefix. +func (db *Database) NewIteratorWithPrefix(prefix []byte) ethdb.Iterator { + db.lock.RLock() + defer db.lock.RUnlock() + + var ( + pr = string(prefix) + keys = make([]string, 0, len(db.db)) + values = make([][]byte, 0, len(db.db)) + ) + // Collect the keys from the memory database corresponding to the given prefix + for key := range db.db { + if strings.HasPrefix(key, pr) { + keys = append(keys, key) + } + } + // Sort the items and retrieve the associated values + sort.Strings(keys) + for _, key := range keys { + values = append(values, db.db[key]) + } + return &iterator{ + keys: keys, + values: values, + } +} + +// Stat returns a particular internal stat of the database. +func (db *Database) Stat(property string) (string, error) { + return "", errors.New("unknown property") +} + +// Compact is not supported on a memory database, but there's no need either as +// a memory database doesn't waste space anyway. +func (db *Database) Compact(start []byte, limit []byte) error { + return nil +} + +// Len returns the number of entries currently present in the memory database. +// +// Note, this method is only used for testing (i.e. not public in general) and +// does not have explicit checks for closed-ness to allow simpler testing code. +func (db *Database) Len() int { + db.lock.RLock() + defer db.lock.RUnlock() + + return len(db.db) +} + +// keyvalue is a key-value tuple tagged with a deletion field to allow creating +// memory-database write batches. +type keyvalue struct { + key []byte + value []byte + delete bool +} + +// batch is a write-only memory batch that commits changes to its host +// database when Write is called. A batch cannot be used concurrently. +type batch struct { + db *Database + writes []keyvalue + size int +} + +// Put inserts the given value into the batch for later committing. +func (b *batch) Put(key, value []byte) error { + b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false}) + b.size += len(value) + return nil +} + +// Delete inserts the a key removal into the batch for later committing. +func (b *batch) Delete(key []byte) error { + b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true}) + b.size += 1 + return nil +} + +// ValueSize retrieves the amount of data queued up for writing. +func (b *batch) ValueSize() int { + return b.size +} + +// Write flushes any accumulated data to the memory database. +func (b *batch) Write() error { + b.db.lock.Lock() + defer b.db.lock.Unlock() + + for _, keyvalue := range b.writes { + if keyvalue.delete { + delete(b.db.db, string(keyvalue.key)) + continue + } + b.db.db[string(keyvalue.key)] = keyvalue.value + } + return nil +} + +// Reset resets the batch for reuse. +func (b *batch) Reset() { + b.writes = b.writes[:0] + b.size = 0 +} + +// Replay replays the batch contents. +func (b *batch) Replay(w ethdb.KeyValueWriter) error { + for _, keyvalue := range b.writes { + if keyvalue.delete { + if err := w.Delete(keyvalue.key); err != nil { + return err + } + continue + } + if err := w.Put(keyvalue.key, keyvalue.value); err != nil { + return err + } + } + return nil +} + +// iterator can walk over the (potentially partial) keyspace of a memory key +// value store. Internally it is a deep copy of the entire iterated state, +// sorted by keys. +type iterator struct { + inited bool + keys []string + values [][]byte +} + +// Next moves the iterator to the next key/value pair. It returns whether the +// iterator is exhausted. +func (it *iterator) Next() bool { + // If the iterator was not yet initialized, do it now + if !it.inited { + it.inited = true + return len(it.keys) > 0 + } + // Iterator already initialize, advance it + if len(it.keys) > 0 { + it.keys = it.keys[1:] + it.values = it.values[1:] + } + return len(it.keys) > 0 +} + +// Error returns any accumulated error. Exhausting all the key/value pairs +// is not considered to be an error. A memory iterator cannot encounter errors. +func (it *iterator) Error() error { + return nil +} + +// Key returns the key of the current key/value pair, or nil if done. The caller +// should not modify the contents of the returned slice, and its contents may +// change on the next call to Next. +func (it *iterator) Key() []byte { + if len(it.keys) > 0 { + return []byte(it.keys[0]) + } + return nil +} + +// Value returns the value of the current key/value pair, or nil if done. The +// caller should not modify the contents of the returned slice, and its contents +// may change on the next call to Next. +func (it *iterator) Value() []byte { + if len(it.values) > 0 { + return it.values[0] + } + return nil +} + +// Release releases associated resources. Release should always succeed and can +// be called multiple times without causing error. +func (it *iterator) Release() { + it.keys, it.values = nil, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/table.go b/vendor/github.com/ethereum/go-ethereum/ethdb/table.go deleted file mode 100644 index 28069c078..000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/table.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 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 ethdb - -type table struct { - db Database - prefix string -} - -// NewTable returns a Database object that prefixes all keys with a given -// string. -func NewTable(db Database, prefix string) Database { - return &table{ - db: db, - prefix: prefix, - } -} - -func (dt *table) Put(key []byte, value []byte) error { - return dt.db.Put(append([]byte(dt.prefix), key...), value) -} - -func (dt *table) Has(key []byte) (bool, error) { - return dt.db.Has(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Get(key []byte) ([]byte, error) { - return dt.db.Get(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Delete(key []byte) error { - return dt.db.Delete(append([]byte(dt.prefix), key...)) -} - -func (dt *table) Close() { - // Do nothing; don't close the underlying DB. -} diff --git a/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go b/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go deleted file mode 100644 index ae83e79ce..000000000 --- a/vendor/github.com/ethereum/go-ethereum/ethdb/table_batch.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 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 ethdb - -type tableBatch struct { - batch Batch - prefix string -} - -// NewTableBatch returns a Batch object which prefixes all keys with a given string. -func NewTableBatch(db Database, prefix string) Batch { - return &tableBatch{db.NewBatch(), prefix} -} - -func (dt *table) NewBatch() Batch { - return &tableBatch{dt.db.NewBatch(), dt.prefix} -} - -func (tb *tableBatch) Put(key, value []byte) error { - return tb.batch.Put(append([]byte(tb.prefix), key...), value) -} - -func (tb *tableBatch) Delete(key []byte) error { - return tb.batch.Delete(append([]byte(tb.prefix), key...)) -} - -func (tb *tableBatch) Write() error { - return tb.batch.Write() -} - -func (tb *tableBatch) ValueSize() int { - return tb.batch.ValueSize() -} - -func (tb *tableBatch) Reset() { - tb.batch.Reset() -} diff --git a/vendor/github.com/ethereum/go-ethereum/go.sum b/vendor/github.com/ethereum/go-ethereum/go.sum new file mode 100644 index 000000000..6feb1e919 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/go.sum @@ -0,0 +1,62 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= +github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/docker v0.0.0-20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= +github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6XPs9nkgTY3u19KXLauXW+J5nB7hEHuX0A= +github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/naoina/toml v0.0.0-20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nsf/termbox-go v0.0.0-20170211012700-3540b76b9c77/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= +github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/peterh/liner v0.0.0-20170902204657-a37ad3984311/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/stretchr/testify v0.0.0-20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190214214411-e77772198cdc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.0.0-20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20170215214335-be0fcc31ae23/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= diff --git a/vendor/github.com/ethereum/go-ethereum/interfaces.go b/vendor/github.com/ethereum/go-ethereum/interfaces.go index be7834406..1ff31f96b 100644 --- a/vendor/github.com/ethereum/go-ethereum/interfaces.go +++ b/vendor/github.com/ethereum/go-ethereum/interfaces.go @@ -144,9 +144,9 @@ type FilterQuery struct { // Examples: // {} or nil matches any topic list // {{A}} matches topic A in first position - // {{}, {B}} matches any topic in first position, B in second position - // {{A}, {B}} matches topic A in first position, B in second position - // {{A, B}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position + // {{}, {B}} matches any topic in first position AND B in second position + // {{A}, {B}} matches topic A in first position AND B in second position + // {{A, B}, {C, D}} matches topic (A OR B) in first position AND (C OR D) in second position Topics [][]common.Hash } diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go index 820e1b186..1d8376e8d 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go @@ -28,9 +28,11 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -42,8 +44,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/tyler-smith/go-bip39" ) const ( @@ -190,13 +191,7 @@ func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI { // Accounts returns the collection of accounts this node manages func (s *PublicAccountAPI) Accounts() []common.Address { - addresses := make([]common.Address, 0) // return [] instead of nil if empty - for _, wallet := range s.am.Wallets() { - for _, account := range wallet.Accounts() { - addresses = append(addresses, account.Address) - } - } - return addresses + return s.am.Accounts() } // PrivateAccountAPI provides an API to access accounts managed by this node. @@ -218,22 +213,16 @@ func NewPrivateAccountAPI(b Backend, nonceLock *AddrLocker) *PrivateAccountAPI { } func NewSubsetOfPrivateAccountAPI(am *accounts.Manager) *PrivateAccountAPI { - return &PrivateAccountAPI{ +return &PrivateAccountAPI{ am: am, nonceLock: nil, b: nil, } } -// ListAccounts will return a list of addresses for accounts this node manages. +// listAccounts will return a list of addresses for accounts this node manages. func (s *PrivateAccountAPI) ListAccounts() []common.Address { - addresses := make([]common.Address, 0) // return [] instead of nil if empty - for _, wallet := range s.am.Wallets() { - for _, account := range wallet.Accounts() { - addresses = append(addresses, account.Address) - } - } - return addresses + return s.am.Accounts() } // rawWallet is a JSON representation of an accounts.Wallet interface, with its @@ -301,6 +290,9 @@ func (s *PrivateAccountAPI) DeriveAccount(url string, path string, pin *bool) (a func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error) { acc, err := fetchKeystore(s.am).NewAccount(password) if err == nil { + log.Info("Your new key was generated", "address", acc.Address) + log.Warn("Please backup your key file!", "path", acc.URL.Path) + log.Warn("Please remember your password!") return acc.Address, nil } return common.Address{}, err @@ -325,7 +317,14 @@ func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (commo // UnlockAccount will unlock the account associated with the given address with // the given password for duration seconds. If duration is nil it will use a // default of 300 seconds. It returns an indication if the account was unlocked. -func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *uint64) (bool, error) { +func (s *PrivateAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) { + // When the API is exposed by external RPC(http, ws etc), unless the user + // explicitly specifies to allow the insecure account unlocking, otherwise + // it is disabled. + if s.b.ExtRPCEnabled() && !s.b.AccountManager().Config().InsecureUnlockAllowed { + return false, errors.New("account unlock with HTTP access is forbidden") + } + const max = uint64(time.Duration(math.MaxInt64) / time.Second) var d time.Duration if duration == nil { @@ -364,11 +363,7 @@ func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args *SendTxArg // Assemble the transaction and sign with the wallet tx := args.toTransaction() - var chainID *big.Int - if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { - chainID = config.ChainID - } - return wallet.SignTxWithPassphrase(account, passwd, tx, chainID) + return wallet.SignTxWithPassphrase(account, passwd, tx, s.b.ChainConfig().ChainID) } // SendTransaction will create a transaction from the given arguments and @@ -386,7 +381,7 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs log.Warn("Failed transaction send attempt", "from", args.From, "to", args.To, "value", args.Value.ToInt(), "err", err) return common.Hash{}, err } - return submitTransaction(ctx, s.b, signed) + return SubmitTransaction(ctx, s.b, signed) } // SignTransaction will create a transaction from the given arguments and @@ -417,18 +412,6 @@ func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args SendTxArgs return &SignTransactionResult{data, signed}, nil } -// signHash is a helper function that calculates a hash for the given message that can be -// safely used to calculate a signature from. -// -// 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)) -} - // Sign calculates an Ethereum ECDSA signature for: // keccack256("\x19Ethereum Signed Message:\n" + len(message) + message)) // @@ -447,12 +430,12 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c return nil, err } // Assemble sign the data with the wallet - signature, err := wallet.SignHashWithPassphrase(account, passwd, signHash(data)) + signature, err := wallet.SignTextWithPassphrase(account, passwd, data) if err != nil { log.Warn("Failed data sign attempt", "address", addr, "err", err) return nil, err } - signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper + signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper return signature, nil } @@ -467,15 +450,15 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { - if len(sig) != 65 { - return common.Address{}, fmt.Errorf("signature must be 65 bytes long") + if len(sig) != crypto.SignatureLength { + return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) } - if sig[64] != 27 && sig[64] != 28 { + if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") } - sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 + sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 - rpk, err := crypto.SigToPub(signHash(data), sig) + rpk, err := crypto.SigToPub(accounts.TextHash(data), sig) if err != nil { return common.Address{}, err } @@ -488,6 +471,48 @@ func (s *PrivateAccountAPI) SignAndSendTransaction(ctx context.Context, args Sen return s.SendTransaction(ctx, args, passwd) } +// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key. +func (s *PrivateAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) { + wallet, err := s.am.Wallet(url) + if err != nil { + return "", err + } + + entropy, err := bip39.NewEntropy(256) + if err != nil { + return "", err + } + + mnemonic, err := bip39.NewMnemonic(entropy) + if err != nil { + return "", err + } + + seed := bip39.NewSeed(mnemonic, "") + + switch wallet := wallet.(type) { + case *scwallet.Wallet: + return mnemonic, wallet.Initialize(seed) + default: + return "", fmt.Errorf("Specified wallet does not support initialization") + } +} + +// Unpair deletes a pairing between wallet and geth. +func (s *PrivateAccountAPI) Unpair(ctx context.Context, url string, pin string) error { + wallet, err := s.am.Wallet(url) + if err != nil { + return err + } + + switch wallet := wallet.(type) { + case *scwallet.Wallet: + return wallet.Unpair([]byte(pin)) + default: + return fmt.Errorf("Specified wallet does not support pairing") + } +} + // PublicBlockChainAPI provides an API to access the Ethereum blockchain. // It offers only methods that operate on public data that is freely available to anyone. type PublicBlockChainAPI struct { @@ -499,6 +524,11 @@ func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI { return &PublicBlockChainAPI{b} } +// ChainId returns the chainID value for transaction replay protection. +func (s *PublicBlockChainAPI) ChainId() *hexutil.Big { + return (*hexutil.Big)(s.b.ChainConfig().ChainID) +} + // BlockNumber returns the block number of the chain head. func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 { header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available @@ -582,13 +612,43 @@ func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Addre }, state.Error() } -// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all -// transactions in the block are returned in full detail, otherwise only the transaction hash is returned. -func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { - block, err := s.b.BlockByNumber(ctx, blockNr) - if block != nil { - response, err := s.rpcOutputBlock(block, true, fullTx) - if err == nil && blockNr == rpc.PendingBlockNumber { +// GetHeaderByNumber returns the requested canonical block header. +// * When blockNr is -1 the chain head is returned. +// * When blockNr is -2 the pending chain head is returned. +func (s *PublicBlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) { + header, err := s.b.HeaderByNumber(ctx, number) + if header != nil && err == nil { + response := s.rpcMarshalHeader(header) + if number == rpc.PendingBlockNumber { + // Pending header need to nil out a few fields + for _, field := range []string{"hash", "nonce", "miner"} { + response[field] = nil + } + } + return response, err + } + return nil, err +} + +// GetHeaderByHash returns the requested header by hash. +func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} { + header, _ := s.b.HeaderByHash(ctx, hash) + if header != nil { + return s.rpcMarshalHeader(header) + } + return nil +} + +// GetBlockByNumber returns the requested canonical block. +// * When blockNr is -1 the chain head is returned. +// * When blockNr is -2 the pending chain head is returned. +// * When fullTx is true all transactions in the block are returned, otherwise +// only the transaction hash is returned. +func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { + block, err := s.b.BlockByNumber(ctx, number) + if block != nil && err == nil { + response, err := s.rpcMarshalBlock(block, true, fullTx) + if err == nil && number == rpc.PendingBlockNumber { // Pending blocks need to nil out a few fields for _, field := range []string{"hash", "nonce", "miner"} { response[field] = nil @@ -601,10 +661,10 @@ func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc. // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full // detail, otherwise only the transaction hash is returned. -func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) { - block, err := s.b.GetBlock(ctx, blockHash) +func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) { + block, err := s.b.BlockByHash(ctx, hash) if block != nil { - return s.rpcOutputBlock(block, true, fullTx) + return s.rpcMarshalBlock(block, true, fullTx) } return nil, err } @@ -620,7 +680,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, return nil, nil } block = types.NewBlockWithHeader(uncles[index]) - return s.rpcOutputBlock(block, false, false) + return s.rpcMarshalBlock(block, false, false) } return nil, err } @@ -628,7 +688,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned. func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) { - block, err := s.b.GetBlock(ctx, blockHash) + block, err := s.b.BlockByHash(ctx, blockHash) if block != nil { uncles := block.Uncles() if index >= hexutil.Uint(len(uncles)) { @@ -636,7 +696,7 @@ func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, b return nil, nil } block = types.NewBlockWithHeader(uncles[index]) - return s.rpcOutputBlock(block, false, false) + return s.rpcMarshalBlock(block, false, false) } return nil, err } @@ -652,7 +712,7 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, bl // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { - if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { + if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { n := hexutil.Uint(len(block.Uncles())) return &n } @@ -683,45 +743,100 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A // CallArgs represents the arguments for a call. type CallArgs struct { - From common.Address `json:"from"` + From *common.Address `json:"from"` To *common.Address `json:"to"` - Gas hexutil.Uint64 `json:"gas"` - GasPrice hexutil.Big `json:"gasPrice"` - Value hexutil.Big `json:"value"` - Data hexutil.Bytes `json:"data"` + Gas *hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + Value *hexutil.Big `json:"value"` + Data *hexutil.Bytes `json:"data"` } -func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, timeout time.Duration, globalGasCap *big.Int) ([]byte, uint64, bool, error) { +// account indicates the overriding fields of account during the execution of +// a message call. +// Note, state and stateDiff can't be specified at the same time. If state is +// set, message execution will only use the data in the given state. Otherwise +// if statDiff is set, all diff will be applied first and then execute the call +// message. +type account struct { + Nonce *hexutil.Uint64 `json:"nonce"` + Code *hexutil.Bytes `json:"code"` + Balance **hexutil.Big `json:"balance"` + State *map[common.Hash]common.Hash `json:"state"` + StateDiff *map[common.Hash]common.Hash `json:"stateDiff"` +} + +func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, overrides map[common.Address]account, vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int) ([]byte, uint64, bool, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) - state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, header, err := b.StateAndHeaderByNumber(ctx, blockNr) if state == nil || err != nil { return nil, 0, false, err } // Set sender address or use a default if none specified - addr := args.From - if addr == (common.Address{}) { - if wallets := s.b.AccountManager().Wallets(); len(wallets) > 0 { + var addr common.Address + if args.From == nil { + if wallets := b.AccountManager().Wallets(); len(wallets) > 0 { if accounts := wallets[0].Accounts(); len(accounts) > 0 { addr = accounts[0].Address } } + } else { + addr = *args.From + } + // Override the fields of specified contracts before execution. + for addr, account := range overrides { + // Override account nonce. + if account.Nonce != nil { + state.SetNonce(addr, uint64(*account.Nonce)) + } + // Override account(contract) code. + if account.Code != nil { + state.SetCode(addr, *account.Code) + } + // Override account balance. + if account.Balance != nil { + state.SetBalance(addr, (*big.Int)(*account.Balance)) + } + if account.State != nil && account.StateDiff != nil { + return nil, 0, false, fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex()) + } + // Replace entire state if caller requires. + if account.State != nil { + state.SetStorage(addr, *account.State) + } + // Apply state diff into specified accounts. + if account.StateDiff != nil { + for key, value := range *account.StateDiff { + state.SetState(addr, key, value) + } + } } // Set default gas & gas price if none were set - gas := uint64(args.Gas) - if gas == 0 { - gas = math.MaxUint64 / 2 + gas := uint64(math.MaxUint64 / 2) + if args.Gas != nil { + gas = uint64(*args.Gas) } if globalGasCap != nil && globalGasCap.Uint64() < gas { log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) gas = globalGasCap.Uint64() } - gasPrice := args.GasPrice.ToInt() - if gasPrice.Sign() == 0 { - gasPrice = new(big.Int).SetUint64(defaultGasPrice) + gasPrice := new(big.Int).SetUint64(defaultGasPrice) + if args.GasPrice != nil { + gasPrice = args.GasPrice.ToInt() } + + value := new(big.Int) + if args.Value != nil { + value = args.Value.ToInt() + } + + var data []byte + if args.Data != nil { + data = []byte(*args.Data) + } + // Create new call message - msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false) + msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false) // Setup context so it may be cancelled the call has completed // or, in case of unmetered gas, setup a context with a timeout. @@ -736,7 +851,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr defer cancel() // Get a new instance of the EVM. - evm, vmError, err := s.b.GetEVM(ctx, msg, state, header) + evm, vmError, err := b.GetEVM(ctx, msg, state, header) if err != nil { return nil, 0, false, err } @@ -754,36 +869,45 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr if err := vmError(); err != nil { return nil, 0, false, err } + // If the timer caused an abort, return an appropriate error message + if evm.Cancelled() { + return nil, 0, false, fmt.Errorf("execution aborted (timeout = %v)", timeout) + } return res, gas, failed, err } // Call executes the given transaction on the state for the given block number. -// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values. -func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - result, _, _, err := s.doCall(ctx, args, blockNr, 5*time.Second, s.b.RPCGasCap()) +// +// Additionally, the caller can specify a batch of contract for fields overriding. +// +// Note, this function doesn't make and changes in the state/blockchain and is +// useful to execute and retrieve values. +func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, overrides *map[common.Address]account) (hexutil.Bytes, error) { + var accounts map[common.Address]account + if overrides != nil { + accounts = *overrides + } + result, _, _, err := DoCall(ctx, s.b, args, blockNr, accounts, vm.Config{}, 5*time.Second, s.b.RPCGasCap()) return (hexutil.Bytes)(result), err } -// EstimateGas returns an estimate of the amount of gas needed to execute the -// given transaction against the current pending block. -func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) { +func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, gasCap *big.Int) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( lo uint64 = params.TxGas - 1 hi uint64 cap uint64 ) - if uint64(args.Gas) >= params.TxGas { - hi = uint64(args.Gas) + if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { + hi = uint64(*args.Gas) } else { - // Retrieve the current pending block to act as the gas ceiling - block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber) + // Retrieve the block to act as the gas ceiling + block, err := b.BlockByNumber(ctx, blockNr) if err != nil { return 0, err } hi = block.GasLimit() } - gasCap := s.b.RPCGasCap() if gasCap != nil && hi > gasCap.Uint64() { log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) hi = gasCap.Uint64() @@ -792,9 +916,9 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h // Create a helper to check if a gas allowance results in an executable transaction executable := func(gas uint64) bool { - args.Gas = hexutil.Uint64(gas) + args.Gas = (*hexutil.Uint64)(&gas) - _, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, 0, gasCap) + _, _, failed, err := DoCall(ctx, b, args, rpc.PendingBlockNumber, nil, vm.Config{}, 0, gasCap) if err != nil || failed { return false } @@ -818,6 +942,12 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h return hexutil.Uint64(hi), nil } +// EstimateGas returns an estimate of the amount of gas needed to execute the +// given transaction against the current pending block. +func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) { + return DoEstimateGas(ctx, s.b, args, rpc.PendingBlockNumber, s.b.RPCGasCap()) +} + // ExecutionResult groups all structured logs emitted by the EVM // while replaying a transaction in debug mode as well as transaction // execution status, the amount of gas used and the return value @@ -842,7 +972,7 @@ type StructLogRes struct { Storage *map[string]string `json:"storage,omitempty"` } -// formatLogs formats EVM returned structured logs for json output +// FormatLogs formats EVM returned structured logs for json output func FormatLogs(logs []vm.StructLog) []StructLogRes { formatted := make([]StructLogRes, len(logs)) for index, trace := range logs { @@ -879,14 +1009,11 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes { return formatted } -// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are -// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain -// transaction hashes. -func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { - head := b.Header() // copies the header once - fields := map[string]interface{}{ +// RPCMarshalHeader converts the given header to the RPC output . +func RPCMarshalHeader(head *types.Header) map[string]interface{} { + return map[string]interface{}{ "number": (*hexutil.Big)(head.Number), - "hash": b.Hash(), + "hash": head.Hash(), "parentHash": head.ParentHash, "nonce": head.Nonce, "mixHash": head.MixDigest, @@ -896,13 +1023,21 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter "miner": head.Coinbase, "difficulty": (*hexutil.Big)(head.Difficulty), "extraData": hexutil.Bytes(head.Extra), - "size": hexutil.Uint64(b.Size()), + "size": hexutil.Uint64(head.Size()), "gasLimit": hexutil.Uint64(head.GasLimit), "gasUsed": hexutil.Uint64(head.GasUsed), "timestamp": hexutil.Uint64(head.Time), "transactionsRoot": head.TxHash, "receiptsRoot": head.ReceiptHash, } +} + +// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are +// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain +// transaction hashes. +func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { + fields := RPCMarshalHeader(block.Header()) + fields["size"] = hexutil.Uint64(block.Size()) if inclTx { formatTx := func(tx *types.Transaction) (interface{}, error) { @@ -910,10 +1045,10 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter } if fullTx { formatTx = func(tx *types.Transaction) (interface{}, error) { - return newRPCTransactionFromBlockHash(b, tx.Hash()), nil + return newRPCTransactionFromBlockHash(block, tx.Hash()), nil } } - txs := b.Transactions() + txs := block.Transactions() transactions := make([]interface{}, len(txs)) var err error for i, tx := range txs { @@ -923,8 +1058,7 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter } fields["transactions"] = transactions } - - uncles := b.Uncles() + uncles := block.Uncles() uncleHashes := make([]common.Hash, len(uncles)) for i, uncle := range uncles { uncleHashes[i] = uncle.Hash() @@ -934,9 +1068,17 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter return fields, nil } -// rpcOutputBlock uses the generalized output filler, then adds the total difficulty field, which requires +// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires // a `PublicBlockchainAPI`. -func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { +func (s *PublicBlockChainAPI) rpcMarshalHeader(header *types.Header) map[string]interface{} { + fields := RPCMarshalHeader(header) + fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(header.Hash())) + return fields +} + +// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires +// a `PublicBlockchainAPI`. +func (s *PublicBlockChainAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { fields, err := RPCMarshalBlock(b, inclTx, fullTx) if err != nil { return nil, err @@ -947,7 +1089,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction type RPCTransaction struct { - BlockHash common.Hash `json:"blockHash"` + BlockHash *common.Hash `json:"blockHash"` BlockNumber *hexutil.Big `json:"blockNumber"` From common.Address `json:"from"` Gas hexutil.Uint64 `json:"gas"` @@ -956,7 +1098,7 @@ type RPCTransaction struct { Input hexutil.Bytes `json:"input"` Nonce hexutil.Uint64 `json:"nonce"` To *common.Address `json:"to"` - TransactionIndex hexutil.Uint `json:"transactionIndex"` + TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` Value *hexutil.Big `json:"value"` V *hexutil.Big `json:"v"` R *hexutil.Big `json:"r"` @@ -987,9 +1129,9 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber S: (*hexutil.Big)(s), } if blockHash != (common.Hash{}) { - result.BlockHash = blockHash + result.BlockHash = &blockHash result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) - result.TransactionIndex = hexutil.Uint(index) + result.TransactionIndex = (*hexutil.Uint64)(&index) } return result } @@ -1050,7 +1192,7 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context. // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { - if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { + if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { n := hexutil.Uint(len(block.Transactions())) return &n } @@ -1067,7 +1209,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx conte // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction { - if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { + if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { return newRPCTransactionFromBlockIndex(block, uint64(index)) } return nil @@ -1083,7 +1225,7 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockNumberAndIndex(ctx co // GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index. func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes { - if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { + if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { return newRPCRawTransactionFromBlockIndex(block, uint64(index)) } return nil @@ -1109,25 +1251,32 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr } // GetTransactionByHash returns the transaction for the given hash -func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) *RPCTransaction { +func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) { // Try to return an already finalized transaction - if tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash); tx != nil { - return newRPCTransaction(tx, blockHash, blockNumber, index) + tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash) + if err != nil { + return nil, err + } + if tx != nil { + return newRPCTransaction(tx, blockHash, blockNumber, index), nil } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { - return newRPCPendingTransaction(tx) + return newRPCPendingTransaction(tx), nil } + // Transaction unknown, return as such - return nil + return nil, nil } // GetRawTransactionByHash returns the bytes of the transaction for the given hash. func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { - var tx *types.Transaction - // Retrieve a finalized transaction, or a pooled otherwise - if tx, _, _, _ = rawdb.ReadTransaction(s.b.ChainDb(), hash); tx == nil { + tx, _, _, _, err := s.b.GetTransaction(ctx, hash) + if err != nil { + return nil, err + } + if tx == nil { if tx = s.b.GetPoolTransaction(hash); tx == nil { // Transaction not found anywhere, abort return nil, nil @@ -1198,11 +1347,7 @@ func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transacti return nil, err } // Request the wallet to sign the transaction - var chainID *big.Int - if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { - chainID = config.ChainID - } - return wallet.SignTx(account, tx, chainID) + return wallet.SignTx(account, tx, s.b.ChainConfig().ChainID) } // SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool. @@ -1221,10 +1366,6 @@ type SendTxArgs struct { // setDefaults is a helper function that fills in default values for unspecified tx fields. func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error { - if args.Gas == nil { - args.Gas = new(hexutil.Uint64) - *(*uint64)(args.Gas) = 90000 - } if args.GasPrice == nil { price, err := b.SuggestPrice(ctx) if err != nil { @@ -1257,15 +1398,37 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error { return errors.New(`contract creation without any data provided`) } } + // Estimate the gas usage if necessary. + if args.Gas == nil { + // For backwards-compatibility reason, we try both input and data + // but input is preferred. + input := args.Input + if input == nil { + input = args.Data + } + callArgs := CallArgs{ + From: &args.From, // From shouldn't be nil + To: args.To, + GasPrice: args.GasPrice, + Value: args.Value, + Data: input, + } + estimated, err := DoEstimateGas(ctx, b, callArgs, rpc.PendingBlockNumber, b.RPCGasCap()) + if err != nil { + return err + } + args.Gas = &estimated + log.Trace("Estimate gas usage automatically", "gas", args.Gas) + } return nil } func (args *SendTxArgs) toTransaction() *types.Transaction { var input []byte - if args.Data != nil { - input = *args.Data - } else if args.Input != nil { + if args.Input != nil { input = *args.Input + } else if args.Data != nil { + input = *args.Data } if args.To == nil { return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) @@ -1273,8 +1436,8 @@ func (args *SendTxArgs) toTransaction() *types.Transaction { return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) } -// submitTransaction is a helper function that submits tx to txPool and logs a message. -func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) { +// SubmitTransaction is a helper function that submits tx to txPool and logs a message. +func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) { if err := b.SendTx(ctx, tx); err != nil { return common.Hash{}, err } @@ -1295,7 +1458,6 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c // SendTransaction creates a transaction for the given argument, sign it and submit it to the // transaction pool. func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) { - // Look up the wallet containing the requested signer account := accounts.Account{Address: args.From} @@ -1318,15 +1480,27 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen // Assemble the transaction and sign with the wallet tx := args.toTransaction() - var chainID *big.Int - if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { - chainID = config.ChainID - } - signed, err := wallet.SignTx(account, tx, chainID) + signed, err := wallet.SignTx(account, tx, s.b.ChainConfig().ChainID) if err != nil { return common.Hash{}, err } - return submitTransaction(ctx, s.b, signed) + return SubmitTransaction(ctx, s.b, signed) +} + +// FillTransaction fills the defaults (nonce, gas, gasPrice) on a given unsigned transaction, +// and returns it to the caller for further processing (signing + broadcast) +func (s *PublicTransactionPoolAPI) FillTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) { + // Set some sanity defaults and terminate on failure + if err := args.setDefaults(ctx, s.b); err != nil { + return nil, err + } + // Assemble the transaction and obtain rlp + tx := args.toTransaction() + data, err := rlp.EncodeToBytes(tx) + if err != nil { + return nil, err + } + return &SignTransactionResult{data, tx}, nil } // SendRawTransaction will add the signed transaction to the transaction pool. @@ -1336,7 +1510,7 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod if err := rlp.DecodeBytes(encodedTx, tx); err != nil { return common.Hash{}, err } - return submitTransaction(ctx, s.b, tx) + return SubmitTransaction(ctx, s.b, tx) } // Sign calculates an ECDSA signature for: @@ -1357,7 +1531,7 @@ func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) return nil, err } // Sign the requested hash with the wallet - signature, err := wallet.SignHash(account, signHash(data)) + signature, err := wallet.SignText(account, data) if err == nil { signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper } @@ -1493,6 +1667,45 @@ func (api *PublicDebugAPI) GetBlockRlp(ctx context.Context, number uint64) (stri return fmt.Sprintf("%x", encoded), nil } +// TestSignCliqueBlock fetches the given block number, and attempts to sign it as a clique header with the +// given address, returning the address of the recovered signature +// +// This is a temporary method to debug the externalsigner integration, +// TODO: Remove this method when the integration is mature +func (api *PublicDebugAPI) TestSignCliqueBlock(ctx context.Context, address common.Address, number uint64) (common.Address, error) { + block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) + if block == nil { + return common.Address{}, fmt.Errorf("block #%d not found", number) + } + header := block.Header() + header.Extra = make([]byte, 32+65) + encoded := clique.CliqueRLP(header) + + // Look up the wallet containing the requested signer + account := accounts.Account{Address: address} + wallet, err := api.b.AccountManager().Find(account) + if err != nil { + return common.Address{}, err + } + + signature, err := wallet.SignData(account, accounts.MimetypeClique, encoded) + if err != nil { + return common.Address{}, err + } + sealHash := clique.SealHash(header).Bytes() + log.Info("test signing of clique block", + "Sealhash", fmt.Sprintf("%x", sealHash), + "signature", fmt.Sprintf("%x", signature)) + pubkey, err := crypto.Ecrecover(sealHash, signature) + if err != nil { + return common.Address{}, err + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + + return signer, nil +} + // PrintBlock retrieves a block and returns its pretty printed form. func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) { block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) @@ -1523,33 +1736,22 @@ func NewPrivateDebugAPI(b Backend) *PrivateDebugAPI { return &PrivateDebugAPI{b: b} } -// ChaindbProperty returns leveldb properties of the chain database. +// ChaindbProperty returns leveldb properties of the key-value database. func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) { - ldb, ok := api.b.ChainDb().(interface { - LDB() *leveldb.DB - }) - if !ok { - return "", fmt.Errorf("chaindbProperty does not work for memory databases") - } if property == "" { property = "leveldb.stats" } else if !strings.HasPrefix(property, "leveldb.") { property = "leveldb." + property } - return ldb.LDB().GetProperty(property) + return api.b.ChainDb().Stat(property) } +// ChaindbCompact flattens the entire key-value database into a single level, +// removing all unused slots and merging all keys. func (api *PrivateDebugAPI) ChaindbCompact() error { - ldb, ok := api.b.ChainDb().(interface { - LDB() *leveldb.DB - }) - if !ok { - return fmt.Errorf("chaindbCompact does not work for memory databases") - } for b := byte(0); b < 255; b++ { log.Info("Compacting chain database", "range", fmt.Sprintf("0x%0.2X-0x%0.2X", b, b+1)) - err := ldb.LDB().CompactRange(util.Range{Start: []byte{b}, Limit: []byte{b + 1}}) - if err != nil { + if err := api.b.ChainDb().Compact([]byte{b}, []byte{b + 1}); err != nil { log.Error("Database compaction failed", "err", err) return err } diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go index 56a3daffa..06c6db33b 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/backend.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "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" @@ -44,23 +45,26 @@ type Backend interface { ChainDb() ethdb.Database EventMux() *event.TypeMux AccountManager() *accounts.Manager + ExtRPCEnabled() bool RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection - // BlockChain API + // Blockchain API SetHead(number uint64) - HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) - BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) - StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) - GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) - GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) - GetTd(blockHash common.Hash) *big.Int + HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) + HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) + BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) + GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) + GetTd(hash common.Hash) *big.Int GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription - // TxPool API + // Transaction pool API SendTx(ctx context.Context, signedTx *types.Transaction) error + GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) GetPoolTransactions() (types.Transactions, error) GetPoolTransaction(txHash common.Hash) *types.Transaction GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) @@ -68,6 +72,13 @@ type Backend interface { TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription + // Filter API + BloomStatus() (uint64, uint64) + GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) + ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) + SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription + SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription + ChainConfig() *params.ChainConfig CurrentBlock() *types.Block } diff --git a/vendor/github.com/ethereum/go-ethereum/les/api.go b/vendor/github.com/ethereum/go-ethereum/les/api.go new file mode 100644 index 000000000..bbef771f0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/api.go @@ -0,0 +1,80 @@ +// Copyright 2019 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 les + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var ( + errNoCheckpoint = errors.New("no local checkpoint provided") + errNotActivated = errors.New("checkpoint registrar is not activated") +) + +// PrivateLightAPI provides an API to access the LES light server or light client. +type PrivateLightAPI struct { + backend *lesCommons +} + +// NewPrivateLightAPI creates a new LES service API. +func NewPrivateLightAPI(backend *lesCommons) *PrivateLightAPI { + return &PrivateLightAPI{backend: backend} +} + +// LatestCheckpoint returns the latest local checkpoint package. +// +// The checkpoint package consists of 4 strings: +// result[0], hex encoded latest section index +// result[1], 32 bytes hex encoded latest section head hash +// result[2], 32 bytes hex encoded latest section canonical hash trie root hash +// result[3], 32 bytes hex encoded latest section bloom trie root hash +func (api *PrivateLightAPI) LatestCheckpoint() ([4]string, error) { + var res [4]string + cp := api.backend.latestLocalCheckpoint() + if cp.Empty() { + return res, errNoCheckpoint + } + res[0] = hexutil.EncodeUint64(cp.SectionIndex) + res[1], res[2], res[3] = cp.SectionHead.Hex(), cp.CHTRoot.Hex(), cp.BloomRoot.Hex() + return res, nil +} + +// GetLocalCheckpoint returns the specific local checkpoint package. +// +// The checkpoint package consists of 3 strings: +// result[0], 32 bytes hex encoded latest section head hash +// result[1], 32 bytes hex encoded latest section canonical hash trie root hash +// result[2], 32 bytes hex encoded latest section bloom trie root hash +func (api *PrivateLightAPI) GetCheckpoint(index uint64) ([3]string, error) { + var res [3]string + cp := api.backend.localCheckpoint(index) + if cp.Empty() { + return res, errNoCheckpoint + } + res[0], res[1], res[2] = cp.SectionHead.Hex(), cp.CHTRoot.Hex(), cp.BloomRoot.Hex() + return res, nil +} + +// GetCheckpointContractAddress returns the contract contract address in hex format. +func (api *PrivateLightAPI) GetCheckpointContractAddress() (string, error) { + if api.backend.oracle == nil { + return "", errNotActivated + } + return api.backend.oracle.config.Address.Hex(), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/api_backend.go b/vendor/github.com/ethereum/go-ethereum/les/api_backend.go index f03d32fed..5cd432dcf 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/api_backend.go +++ b/vendor/github.com/ethereum/go-ethereum/les/api_backend.go @@ -18,6 +18,7 @@ package les import ( "context" + "errors" "math/big" "github.com/ethereum/go-ethereum/accounts" @@ -39,8 +40,9 @@ import ( ) type LesApiBackend struct { - eth *LightEthereum - gpo *gasprice.Oracle + extRPCEnabled bool + eth *LightEthereum + gpo *gasprice.Oracle } func (b *LesApiBackend) ChainConfig() *params.ChainConfig { @@ -52,41 +54,44 @@ func (b *LesApiBackend) CurrentBlock() *types.Block { } func (b *LesApiBackend) SetHead(number uint64) { - b.eth.protocolManager.downloader.Cancel() + b.eth.handler.downloader.Cancel() b.eth.blockchain.SetHead(number) } -func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { - if blockNr == rpc.LatestBlockNumber || blockNr == rpc.PendingBlockNumber { +func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { + if number == rpc.LatestBlockNumber || number == rpc.PendingBlockNumber { return b.eth.blockchain.CurrentHeader(), nil } - return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(blockNr)) + return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(number)) } func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { return b.eth.blockchain.GetHeaderByHash(hash), nil } -func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) { - header, err := b.HeaderByNumber(ctx, blockNr) +func (b *LesApiBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { + header, err := b.HeaderByNumber(ctx, number) if header == nil || err != nil { return nil, err } - return b.GetBlock(ctx, header.Hash()) + return b.BlockByHash(ctx, header.Hash()) } -func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) { - header, err := b.HeaderByNumber(ctx, blockNr) - if header == nil || err != nil { +func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return b.eth.blockchain.GetBlockByHash(ctx, hash) +} + +func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { + header, err := b.HeaderByNumber(ctx, number) + if err != nil { return nil, nil, err } + if header == nil { + return nil, nil, errors.New("header not found") + } return light.NewState(ctx, header, b.eth.odr), header, nil } -func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) { - return b.eth.blockchain.GetBlockByHash(ctx, blockHash) -} - func (b *LesApiBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil { return light.GetBlockReceipts(ctx, b.eth.odr, hash, *number) @@ -127,6 +132,10 @@ func (b *LesApiBackend) GetPoolTransaction(txHash common.Hash) *types.Transactio return b.eth.txPool.GetTransaction(txHash) } +func (b *LesApiBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { + return light.GetTransaction(ctx, b.eth.odr, txHash) +} + func (b *LesApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { return b.eth.txPool.GetNonce(ctx, addr) } @@ -187,6 +196,10 @@ func (b *LesApiBackend) AccountManager() *accounts.Manager { return b.eth.accountManager } +func (b *LesApiBackend) ExtRPCEnabled() bool { + return b.extRPCEnabled +} + func (b *LesApiBackend) RPCGasCap() *big.Int { return b.eth.config.RPCGasCap } diff --git a/vendor/github.com/ethereum/go-ethereum/les/balance.go b/vendor/github.com/ethereum/go-ethereum/les/balance.go new file mode 100644 index 000000000..a36a997cf --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/balance.go @@ -0,0 +1,381 @@ +// Copyright 2019 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 les + +import ( + "sync" + "time" + + "github.com/ethereum/go-ethereum/common/mclock" +) + +const ( + balanceCallbackQueue = iota + balanceCallbackZero + balanceCallbackCount +) + +// balanceTracker keeps track of the positive and negative balances of a connected +// client and calculates actual and projected future priority values required by +// prque.LazyQueue. +type balanceTracker struct { + lock sync.Mutex + clock mclock.Clock + stopped bool + capacity uint64 + balance balance + timeFactor, requestFactor float64 + negTimeFactor, negRequestFactor float64 + sumReqCost uint64 + lastUpdate, nextUpdate, initTime mclock.AbsTime + updateEvent mclock.Timer + // since only a limited and fixed number of callbacks are needed, they are + // stored in a fixed size array ordered by priority threshold. + callbacks [balanceCallbackCount]balanceCallback + // callbackIndex maps balanceCallback constants to callbacks array indexes (-1 if not active) + callbackIndex [balanceCallbackCount]int + callbackCount int // number of active callbacks +} + +// balance represents a pair of positive and negative balances +type balance struct { + pos, neg uint64 +} + +// balanceCallback represents a single callback that is activated when client priority +// reaches the given threshold +type balanceCallback struct { + id int + threshold int64 + callback func() +} + +// init initializes balanceTracker +func (bt *balanceTracker) init(clock mclock.Clock, capacity uint64) { + bt.clock = clock + bt.initTime = clock.Now() + for i := range bt.callbackIndex { + bt.callbackIndex[i] = -1 + } + bt.capacity = capacity +} + +// stop shuts down the balance tracker +func (bt *balanceTracker) stop(now mclock.AbsTime) { + bt.lock.Lock() + defer bt.lock.Unlock() + + bt.stopped = true + bt.updateBalance(now) + bt.negTimeFactor = 0 + bt.negRequestFactor = 0 + bt.timeFactor = 0 + bt.requestFactor = 0 + if bt.updateEvent != nil { + bt.updateEvent.Stop() + bt.updateEvent = nil + } +} + +// balanceToPriority converts a balance to a priority value. Higher priority means +// first to disconnect. Positive balance translates to negative priority. If positive +// balance is zero then negative balance translates to a positive priority. +func (bt *balanceTracker) balanceToPriority(b balance) int64 { + if b.pos > 0 { + return ^int64(b.pos / bt.capacity) + } + return int64(b.neg) +} + +// reducedBalance estimates the reduced balance at a given time in the fututre based +// on the current balance, the time factor and an estimated average request cost per time ratio +func (bt *balanceTracker) reducedBalance(at mclock.AbsTime, avgReqCost float64) balance { + dt := float64(at - bt.lastUpdate) + b := bt.balance + if b.pos != 0 { + factor := bt.timeFactor + bt.requestFactor*avgReqCost + diff := uint64(dt * factor) + if diff <= b.pos { + b.pos -= diff + dt = 0 + } else { + dt -= float64(b.pos) / factor + b.pos = 0 + } + } + if dt != 0 { + factor := bt.negTimeFactor + bt.negRequestFactor*avgReqCost + b.neg += uint64(dt * factor) + } + return b +} + +// timeUntil calculates the remaining time needed to reach a given priority level +// assuming that no requests are processed until then. If the given level is never +// reached then (0, false) is returned. +// Note: the function assumes that the balance has been recently updated and +// calculates the time starting from the last update. +func (bt *balanceTracker) timeUntil(priority int64) (time.Duration, bool) { + var dt float64 + if bt.balance.pos != 0 { + if bt.timeFactor < 1e-100 { + return 0, false + } + if priority < 0 { + newBalance := uint64(^priority) * bt.capacity + if newBalance > bt.balance.pos { + return 0, false + } + dt = float64(bt.balance.pos-newBalance) / bt.timeFactor + return time.Duration(dt), true + } else { + dt = float64(bt.balance.pos) / bt.timeFactor + } + } else { + if priority < 0 { + return 0, false + } + } + // if we have a positive balance then dt equals the time needed to get it to zero + if uint64(priority) > bt.balance.neg { + if bt.negTimeFactor < 1e-100 { + return 0, false + } + dt += float64(uint64(priority)-bt.balance.neg) / bt.negTimeFactor + } + return time.Duration(dt), true +} + +// getPriority returns the actual priority based on the current balance +func (bt *balanceTracker) getPriority(now mclock.AbsTime) int64 { + bt.lock.Lock() + defer bt.lock.Unlock() + + bt.updateBalance(now) + return bt.balanceToPriority(bt.balance) +} + +// estimatedPriority gives an upper estimate for the priority at a given time in the future. +// If addReqCost is true then an average request cost per time is assumed that is twice the +// average cost per time in the current session. If false, zero request cost is assumed. +func (bt *balanceTracker) estimatedPriority(at mclock.AbsTime, addReqCost bool) int64 { + bt.lock.Lock() + defer bt.lock.Unlock() + + var avgReqCost float64 + if addReqCost { + dt := time.Duration(bt.lastUpdate - bt.initTime) + if dt > time.Second { + avgReqCost = float64(bt.sumReqCost) * 2 / float64(dt) + } + } + return bt.balanceToPriority(bt.reducedBalance(at, avgReqCost)) +} + +// updateBalance updates balance based on the time factor +func (bt *balanceTracker) updateBalance(now mclock.AbsTime) { + if now > bt.lastUpdate { + bt.balance = bt.reducedBalance(now, 0) + bt.lastUpdate = now + } +} + +// checkCallbacks checks whether the threshold of any of the active callbacks +// have been reached and calls them if necessary. It also sets up or updates +// a scheduled event to ensure that is will be called again just after the next +// threshold has been reached. +// Note: checkCallbacks assumes that the balance has been recently updated. +func (bt *balanceTracker) checkCallbacks(now mclock.AbsTime) { + if bt.callbackCount == 0 { + return + } + pri := bt.balanceToPriority(bt.balance) + for bt.callbackCount != 0 && bt.callbacks[bt.callbackCount-1].threshold <= pri { + bt.callbackCount-- + bt.callbackIndex[bt.callbacks[bt.callbackCount].id] = -1 + go bt.callbacks[bt.callbackCount].callback() + } + if bt.callbackCount != 0 { + d, ok := bt.timeUntil(bt.callbacks[bt.callbackCount-1].threshold) + if !ok { + bt.nextUpdate = 0 + bt.updateAfter(0) + return + } + if bt.nextUpdate == 0 || bt.nextUpdate > now+mclock.AbsTime(d) { + if d > time.Second { + // Note: if the scheduled update is not in the very near future then we + // schedule the update a bit earlier. This way we do need to update a few + // extra times but don't need to reschedule every time a processed request + // brings the expected firing time a little bit closer. + d = ((d - time.Second) * 7 / 8) + time.Second + } + bt.nextUpdate = now + mclock.AbsTime(d) + bt.updateAfter(d) + } + } else { + bt.nextUpdate = 0 + bt.updateAfter(0) + } +} + +// updateAfter schedules a balance update and callback check in the future +func (bt *balanceTracker) updateAfter(dt time.Duration) { + if bt.updateEvent == nil || bt.updateEvent.Stop() { + if dt == 0 { + bt.updateEvent = nil + } else { + bt.updateEvent = bt.clock.AfterFunc(dt, func() { + bt.lock.Lock() + defer bt.lock.Unlock() + + if bt.callbackCount != 0 { + now := bt.clock.Now() + bt.updateBalance(now) + bt.checkCallbacks(now) + } + }) + } + } +} + +// requestCost should be called after serving a request for the given peer +func (bt *balanceTracker) requestCost(cost uint64) { + bt.lock.Lock() + defer bt.lock.Unlock() + + if bt.stopped { + return + } + now := bt.clock.Now() + bt.updateBalance(now) + fcost := float64(cost) + + if bt.balance.pos != 0 { + if bt.requestFactor != 0 { + c := uint64(fcost * bt.requestFactor) + if bt.balance.pos >= c { + bt.balance.pos -= c + fcost = 0 + } else { + fcost *= 1 - float64(bt.balance.pos)/float64(c) + bt.balance.pos = 0 + } + bt.checkCallbacks(now) + } else { + fcost = 0 + } + } + if fcost > 0 { + if bt.negRequestFactor != 0 { + bt.balance.neg += uint64(fcost * bt.negRequestFactor) + bt.checkCallbacks(now) + } + } + bt.sumReqCost += cost +} + +// getBalance returns the current positive and negative balance +func (bt *balanceTracker) getBalance(now mclock.AbsTime) (uint64, uint64) { + bt.lock.Lock() + defer bt.lock.Unlock() + + bt.updateBalance(now) + return bt.balance.pos, bt.balance.neg +} + +// setBalance sets the positive and negative balance to the given values +func (bt *balanceTracker) setBalance(pos, neg uint64) error { + bt.lock.Lock() + defer bt.lock.Unlock() + + now := bt.clock.Now() + bt.updateBalance(now) + bt.balance.pos = pos + bt.balance.neg = neg + bt.checkCallbacks(now) + return nil +} + +// setFactors sets the price factors. timeFactor is the price of a nanosecond of +// connection while requestFactor is the price of a "realCost" unit. +func (bt *balanceTracker) setFactors(neg bool, timeFactor, requestFactor float64) { + bt.lock.Lock() + defer bt.lock.Unlock() + + if bt.stopped { + return + } + now := bt.clock.Now() + bt.updateBalance(now) + if neg { + bt.negTimeFactor = timeFactor + bt.negRequestFactor = requestFactor + } else { + bt.timeFactor = timeFactor + bt.requestFactor = requestFactor + } + bt.checkCallbacks(now) +} + +// setCallback sets up a one-time callback to be called when priority reaches +// the threshold. If it has already reached the threshold the callback is called +// immediately. +func (bt *balanceTracker) addCallback(id int, threshold int64, callback func()) { + bt.lock.Lock() + defer bt.lock.Unlock() + + bt.removeCb(id) + idx := 0 + for idx < bt.callbackCount && threshold < bt.callbacks[idx].threshold { + idx++ + } + for i := bt.callbackCount - 1; i >= idx; i-- { + bt.callbackIndex[bt.callbacks[i].id]++ + bt.callbacks[i+1] = bt.callbacks[i] + } + bt.callbackCount++ + bt.callbackIndex[id] = idx + bt.callbacks[idx] = balanceCallback{id, threshold, callback} + now := bt.clock.Now() + bt.updateBalance(now) + bt.checkCallbacks(now) +} + +// removeCallback removes the given callback and returns true if it was active +func (bt *balanceTracker) removeCallback(id int) bool { + bt.lock.Lock() + defer bt.lock.Unlock() + + return bt.removeCb(id) +} + +// removeCb removes the given callback and returns true if it was active +// Note: should be called while bt.lock is held +func (bt *balanceTracker) removeCb(id int) bool { + idx := bt.callbackIndex[id] + if idx == -1 { + return false + } + bt.callbackIndex[id] = -1 + for i := idx; i < bt.callbackCount-1; i++ { + bt.callbackIndex[bt.callbacks[i+1].id]-- + bt.callbacks[i] = bt.callbacks[i+1] + } + bt.callbackCount-- + return true +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/benchmark.go b/vendor/github.com/ethereum/go-ethereum/les/benchmark.go new file mode 100644 index 000000000..42eeef10f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/benchmark.go @@ -0,0 +1,354 @@ +// Copyright 2019 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 les + +import ( + "encoding/binary" + "fmt" + "math/big" + "math/rand" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/les/flowcontrol" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// requestBenchmark is an interface for different randomized request generators +type requestBenchmark interface { + // init initializes the generator for generating the given number of randomized requests + init(h *serverHandler, count int) error + // request initiates sending a single request to the given peer + request(peer *peer, index int) error +} + +// benchmarkBlockHeaders implements requestBenchmark +type benchmarkBlockHeaders struct { + amount, skip int + reverse, byHash bool + offset, randMax int64 + hashes []common.Hash +} + +func (b *benchmarkBlockHeaders) init(h *serverHandler, count int) error { + d := int64(b.amount-1) * int64(b.skip+1) + b.offset = 0 + b.randMax = h.blockchain.CurrentHeader().Number.Int64() + 1 - d + if b.randMax < 0 { + return fmt.Errorf("chain is too short") + } + if b.reverse { + b.offset = d + } + if b.byHash { + b.hashes = make([]common.Hash, count) + for i := range b.hashes { + b.hashes[i] = rawdb.ReadCanonicalHash(h.chainDb, uint64(b.offset+rand.Int63n(b.randMax))) + } + } + return nil +} + +func (b *benchmarkBlockHeaders) request(peer *peer, index int) error { + if b.byHash { + return peer.RequestHeadersByHash(0, 0, b.hashes[index], b.amount, b.skip, b.reverse) + } else { + return peer.RequestHeadersByNumber(0, 0, uint64(b.offset+rand.Int63n(b.randMax)), b.amount, b.skip, b.reverse) + } +} + +// benchmarkBodiesOrReceipts implements requestBenchmark +type benchmarkBodiesOrReceipts struct { + receipts bool + hashes []common.Hash +} + +func (b *benchmarkBodiesOrReceipts) init(h *serverHandler, count int) error { + randMax := h.blockchain.CurrentHeader().Number.Int64() + 1 + b.hashes = make([]common.Hash, count) + for i := range b.hashes { + b.hashes[i] = rawdb.ReadCanonicalHash(h.chainDb, uint64(rand.Int63n(randMax))) + } + return nil +} + +func (b *benchmarkBodiesOrReceipts) request(peer *peer, index int) error { + if b.receipts { + return peer.RequestReceipts(0, 0, []common.Hash{b.hashes[index]}) + } else { + return peer.RequestBodies(0, 0, []common.Hash{b.hashes[index]}) + } +} + +// benchmarkProofsOrCode implements requestBenchmark +type benchmarkProofsOrCode struct { + code bool + headHash common.Hash +} + +func (b *benchmarkProofsOrCode) init(h *serverHandler, count int) error { + b.headHash = h.blockchain.CurrentHeader().Hash() + return nil +} + +func (b *benchmarkProofsOrCode) request(peer *peer, index int) error { + key := make([]byte, 32) + rand.Read(key) + if b.code { + return peer.RequestCode(0, 0, []CodeReq{{BHash: b.headHash, AccKey: key}}) + } else { + return peer.RequestProofs(0, 0, []ProofReq{{BHash: b.headHash, Key: key}}) + } +} + +// benchmarkHelperTrie implements requestBenchmark +type benchmarkHelperTrie struct { + bloom bool + reqCount int + sectionCount, headNum uint64 +} + +func (b *benchmarkHelperTrie) init(h *serverHandler, count int) error { + if b.bloom { + b.sectionCount, b.headNum, _ = h.server.bloomTrieIndexer.Sections() + } else { + b.sectionCount, _, _ = h.server.chtIndexer.Sections() + b.headNum = b.sectionCount*params.CHTFrequency - 1 + } + if b.sectionCount == 0 { + return fmt.Errorf("no processed sections available") + } + return nil +} + +func (b *benchmarkHelperTrie) request(peer *peer, index int) error { + reqs := make([]HelperTrieReq, b.reqCount) + + if b.bloom { + bitIdx := uint16(rand.Intn(2048)) + for i := range reqs { + key := make([]byte, 10) + binary.BigEndian.PutUint16(key[:2], bitIdx) + binary.BigEndian.PutUint64(key[2:], uint64(rand.Int63n(int64(b.sectionCount)))) + reqs[i] = HelperTrieReq{Type: htBloomBits, TrieIdx: b.sectionCount - 1, Key: key} + } + } else { + for i := range reqs { + key := make([]byte, 8) + binary.BigEndian.PutUint64(key[:], uint64(rand.Int63n(int64(b.headNum)))) + reqs[i] = HelperTrieReq{Type: htCanonical, TrieIdx: b.sectionCount - 1, Key: key, AuxReq: auxHeader} + } + } + + return peer.RequestHelperTrieProofs(0, 0, reqs) +} + +// benchmarkTxSend implements requestBenchmark +type benchmarkTxSend struct { + txs types.Transactions +} + +func (b *benchmarkTxSend) init(h *serverHandler, count int) error { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + signer := types.NewEIP155Signer(big.NewInt(18)) + b.txs = make(types.Transactions, count) + + for i := range b.txs { + data := make([]byte, txSizeCostLimit) + rand.Read(data) + tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data), signer, key) + if err != nil { + panic(err) + } + b.txs[i] = tx + } + return nil +} + +func (b *benchmarkTxSend) request(peer *peer, index int) error { + enc, _ := rlp.EncodeToBytes(types.Transactions{b.txs[index]}) + return peer.SendTxs(0, 0, enc) +} + +// benchmarkTxStatus implements requestBenchmark +type benchmarkTxStatus struct{} + +func (b *benchmarkTxStatus) init(h *serverHandler, count int) error { + return nil +} + +func (b *benchmarkTxStatus) request(peer *peer, index int) error { + var hash common.Hash + rand.Read(hash[:]) + return peer.RequestTxStatus(0, 0, []common.Hash{hash}) +} + +// benchmarkSetup stores measurement data for a single benchmark type +type benchmarkSetup struct { + req requestBenchmark + totalCount int + totalTime, avgTime time.Duration + maxInSize, maxOutSize uint32 + err error +} + +// runBenchmark runs a benchmark cycle for all benchmark types in the specified +// number of passes +func (h *serverHandler) runBenchmark(benchmarks []requestBenchmark, passCount int, targetTime time.Duration) []*benchmarkSetup { + setup := make([]*benchmarkSetup, len(benchmarks)) + for i, b := range benchmarks { + setup[i] = &benchmarkSetup{req: b} + } + for i := 0; i < passCount; i++ { + log.Info("Running benchmark", "pass", i+1, "total", passCount) + todo := make([]*benchmarkSetup, len(benchmarks)) + copy(todo, setup) + for len(todo) > 0 { + // select a random element + index := rand.Intn(len(todo)) + next := todo[index] + todo[index] = todo[len(todo)-1] + todo = todo[:len(todo)-1] + + if next.err == nil { + // calculate request count + count := 50 + if next.totalTime > 0 { + count = int(uint64(next.totalCount) * uint64(targetTime) / uint64(next.totalTime)) + } + if err := h.measure(next, count); err != nil { + next.err = err + } + } + } + } + log.Info("Benchmark completed") + + for _, s := range setup { + if s.err == nil { + s.avgTime = s.totalTime / time.Duration(s.totalCount) + } + } + return setup +} + +// meteredPipe implements p2p.MsgReadWriter and remembers the largest single +// message size sent through the pipe +type meteredPipe struct { + rw p2p.MsgReadWriter + maxSize uint32 +} + +func (m *meteredPipe) ReadMsg() (p2p.Msg, error) { + return m.rw.ReadMsg() +} + +func (m *meteredPipe) WriteMsg(msg p2p.Msg) error { + if msg.Size > m.maxSize { + m.maxSize = msg.Size + } + return m.rw.WriteMsg(msg) +} + +// measure runs a benchmark for a single type in a single pass, with the given +// number of requests +func (h *serverHandler) measure(setup *benchmarkSetup, count int) error { + clientPipe, serverPipe := p2p.MsgPipe() + clientMeteredPipe := &meteredPipe{rw: clientPipe} + serverMeteredPipe := &meteredPipe{rw: serverPipe} + var id enode.ID + rand.Read(id[:]) + + clientPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe) + serverPeer := newPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "server", nil), serverMeteredPipe) + serverPeer.sendQueue = newExecQueue(count) + serverPeer.announceType = announceTypeNone + serverPeer.fcCosts = make(requestCostTable) + c := &requestCosts{} + for code := range requests { + serverPeer.fcCosts[code] = c + } + serverPeer.fcParams = flowcontrol.ServerParams{BufLimit: 1, MinRecharge: 1} + serverPeer.fcClient = flowcontrol.NewClientNode(h.server.fcManager, serverPeer.fcParams) + defer serverPeer.fcClient.Disconnect() + + if err := setup.req.init(h, count); err != nil { + return err + } + + errCh := make(chan error, 10) + start := mclock.Now() + + go func() { + for i := 0; i < count; i++ { + if err := setup.req.request(clientPeer, i); err != nil { + errCh <- err + return + } + } + }() + go func() { + for i := 0; i < count; i++ { + if err := h.handleMsg(serverPeer, &sync.WaitGroup{}); err != nil { + errCh <- err + return + } + } + }() + go func() { + for i := 0; i < count; i++ { + msg, err := clientPipe.ReadMsg() + if err != nil { + errCh <- err + return + } + var i interface{} + msg.Decode(&i) + } + // at this point we can be sure that the other two + // goroutines finished successfully too + close(errCh) + }() + select { + case err := <-errCh: + if err != nil { + return err + } + case <-h.closeCh: + clientPipe.Close() + serverPipe.Close() + return fmt.Errorf("Benchmark cancelled") + } + + setup.totalTime += time.Duration(mclock.Now() - start) + setup.totalCount += count + setup.maxInSize = clientMeteredPipe.maxSize + setup.maxOutSize = serverMeteredPipe.maxSize + clientPipe.Close() + serverPipe.Close() + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/bloombits.go b/vendor/github.com/ethereum/go-ethereum/les/bloombits.go index aea0fcd5f..a98524ce2 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/bloombits.go +++ b/vendor/github.com/ethereum/go-ethereum/les/bloombits.go @@ -46,9 +46,10 @@ const ( func (eth *LightEthereum) startBloomHandlers(sectionSize uint64) { for i := 0; i < bloomServiceThreads; i++ { go func() { + defer eth.wg.Done() for { select { - case <-eth.shutdownChan: + case <-eth.closeCh: return case request := <-eth.bloomRequests: diff --git a/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go b/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go new file mode 100644 index 000000000..4695fbc16 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/checkpointoracle.go @@ -0,0 +1,158 @@ +// Copyright 2019 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 les + +import ( + "encoding/binary" + "sync/atomic" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/contracts/checkpointoracle" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +// checkpointOracle is responsible for offering the latest stable checkpoint +// generated and announced by the contract admins on-chain. The checkpoint is +// verified by clients locally during the checkpoint syncing. +type checkpointOracle struct { + config *params.CheckpointOracleConfig + contract *checkpointoracle.CheckpointOracle + + // Whether the contract backend is set. + running int32 + + getLocal func(uint64) params.TrustedCheckpoint // Function used to retrieve local checkpoint + syncDoneHook func() // Function used to notify that light syncing has completed. +} + +// newCheckpointOracle returns a checkpoint registrar handler. +func newCheckpointOracle(config *params.CheckpointOracleConfig, getLocal func(uint64) params.TrustedCheckpoint) *checkpointOracle { + if config == nil { + log.Info("Checkpoint registrar is not enabled") + return nil + } + if config.Address == (common.Address{}) || uint64(len(config.Signers)) < config.Threshold { + log.Warn("Invalid checkpoint registrar config") + return nil + } + log.Info("Configured checkpoint registrar", "address", config.Address, "signers", len(config.Signers), "threshold", config.Threshold) + + return &checkpointOracle{ + config: config, + getLocal: getLocal, + } +} + +// start binds the registrar contract and start listening to the +// newCheckpointEvent for the server side. +func (reg *checkpointOracle) start(backend bind.ContractBackend) { + contract, err := checkpointoracle.NewCheckpointOracle(reg.config.Address, backend) + if err != nil { + log.Error("Oracle contract binding failed", "err", err) + return + } + if !atomic.CompareAndSwapInt32(®.running, 0, 1) { + log.Error("Already bound and listening to registrar") + return + } + reg.contract = contract +} + +// isRunning returns an indicator whether the registrar is running. +func (reg *checkpointOracle) isRunning() bool { + return atomic.LoadInt32(®.running) == 1 +} + +// stableCheckpoint returns the stable checkpoint which was generated by local +// indexers and announced by trusted signers. +func (reg *checkpointOracle) stableCheckpoint() (*params.TrustedCheckpoint, uint64) { + // Retrieve the latest checkpoint from the contract, abort if empty + latest, hash, height, err := reg.contract.Contract().GetLatestCheckpoint(nil) + if err != nil || (latest == 0 && hash == [32]byte{}) { + return nil, 0 + } + local := reg.getLocal(latest) + + // The following scenarios may occur: + // + // * local node is out of sync so that it doesn't have the + // checkpoint which registered in the contract. + // * local checkpoint doesn't match with the registered one. + // + // In both cases, server won't send the **stable** checkpoint + // to the client(no worry, client can use hardcoded one instead). + if local.HashEqual(common.Hash(hash)) { + return &local, height.Uint64() + } + return nil, 0 +} + +// verifySigners recovers the signer addresses according to the signature and +// checks whether there are enough approvals to finalize the checkpoint. +func (reg *checkpointOracle) verifySigners(index uint64, hash [32]byte, signatures [][]byte) (bool, []common.Address) { + // Short circuit if the given signatures doesn't reach the threshold. + if len(signatures) < int(reg.config.Threshold) { + return false, nil + } + var ( + signers []common.Address + checked = make(map[common.Address]struct{}) + ) + for i := 0; i < len(signatures); i++ { + if len(signatures[i]) != 65 { + continue + } + // EIP 191 style signatures + // + // Arguments when calculating hash to validate + // 1: byte(0x19) - the initial 0x19 byte + // 2: byte(0) - the version byte (data with intended validator) + // 3: this - the validator address + // -- Application specific data + // 4 : checkpoint section_index (uint64) + // 5 : checkpoint hash (bytes32) + // hash = keccak256(checkpoint_index, section_head, cht_root, bloom_root) + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, index) + data := append([]byte{0x19, 0x00}, append(reg.config.Address.Bytes(), append(buf, hash[:]...)...)...) + signatures[i][64] -= 27 // Transform V from 27/28 to 0/1 according to the yellow paper for verification. + pubkey, err := crypto.Ecrecover(crypto.Keccak256(data), signatures[i]) + if err != nil { + return false, nil + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + if _, exist := checked[signer]; exist { + continue + } + for _, s := range reg.config.Signers { + if s == signer { + signers = append(signers, signer) + checked[signer] = struct{}{} + } + } + } + threshold := reg.config.Threshold + if uint64(len(signers)) < threshold { + log.Warn("Not enough signers to approve checkpoint", "signers", len(signers), "threshold", threshold) + return false, nil + } + return true, signers +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/backend.go b/vendor/github.com/ethereum/go-ethereum/les/client.go similarity index 71% rename from vendor/github.com/ethereum/go-ethereum/les/backend.go rename to vendor/github.com/ethereum/go-ethereum/les/client.go index cd99f8f81..b367681f3 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/les/client.go @@ -19,12 +19,12 @@ package les import ( "fmt" - "sync" - "time" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" @@ -40,98 +40,100 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/discv5" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" - rpc "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/rpc" ) type LightEthereum struct { lesCommons - odr *LesOdr - relay *LesTxRelay - chainConfig *params.ChainConfig - // Channel for shutting down the service - shutdownChan chan bool - - // Handlers - peers *peerSet + reqDist *requestDistributor + retriever *retrieveManager + odr *LesOdr + relay *lesTxRelay + handler *clientHandler txPool *light.TxPool blockchain *light.LightChain serverPool *serverPool - reqDist *requestDistributor - retriever *retrieveManager bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests - bloomIndexer *core.ChainIndexer - - ApiBackend *LesApiBackend + bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports + ApiBackend *LesApiBackend eventMux *event.TypeMux engine consensus.Engine accountManager *accounts.Manager - - networkId uint64 - netRPCService *ethapi.PublicNetAPI - - wg sync.WaitGroup + netRPCService *ethapi.PublicNetAPI } func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { - chainDb, err := eth.CreateDB(ctx, config, "lightchaindata") + chainDb, err := ctx.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/") if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.ConstantinopleOverride) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideIstanbul) if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { return nil, genesisErr } log.Info("Initialised chain configuration", "config", chainConfig) peers := newPeerSet() - quitSync := make(chan struct{}) - leth := &LightEthereum{ lesCommons: lesCommons{ - chainDb: chainDb, - config: config, - iConfig: light.DefaultClientIndexerConfig, + genesis: genesisHash, + config: config, + chainConfig: chainConfig, + iConfig: light.DefaultClientIndexerConfig, + chainDb: chainDb, + peers: peers, + closeCh: make(chan struct{}), }, - chainConfig: chainConfig, eventMux: ctx.EventMux, - peers: peers, - reqDist: newRequestDistributor(peers, quitSync), + reqDist: newRequestDistributor(peers, &mclock.System{}), accountManager: ctx.AccountManager, engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb), - shutdownChan: make(chan bool), - networkId: config.NetworkId, bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), + serverPool: newServerPool(chainDb, config.UltraLightServers), } - - var trustedNodes []string - if leth.config.ULC != nil { - trustedNodes = leth.config.ULC.TrustedServers - } - leth.relay = NewLesTxRelay(peers, leth.reqDist) - leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg, trustedNodes) leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool) + leth.relay = newLesTxRelay(peers, leth.retriever) leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.retriever) - leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, params.CHTFrequencyClient, params.HelperTrieConfirmations) + leth.chtIndexer = light.NewChtIndexer(chainDb, leth.odr, params.CHTFrequency, params.HelperTrieConfirmations) leth.bloomTrieIndexer = light.NewBloomTrieIndexer(chainDb, leth.odr, params.BloomBitsBlocksClient, params.BloomTrieFrequency) leth.odr.SetIndexers(leth.chtIndexer, leth.bloomTrieIndexer, leth.bloomIndexer) + checkpoint := config.Checkpoint + if checkpoint == nil { + checkpoint = params.TrustedCheckpoints[genesisHash] + } // Note: NewLightChain adds the trusted checkpoint so it needs an ODR with // indexers already set but not started yet - if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine); err != nil { + if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, checkpoint); err != nil { return nil, err } + leth.chainReader = leth.blockchain + leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) + + // Set up checkpoint oracle. + oracle := config.CheckpointOracle + if oracle == nil { + oracle = params.CheckpointOracles[genesisHash] + } + leth.oracle = newCheckpointOracle(oracle, leth.localCheckpoint) + // Note: AddChildIndexer starts the update process for the child leth.bloomIndexer.AddChildIndexer(leth.bloomTrieIndexer) leth.chtIndexer.Start(leth.blockchain) leth.bloomIndexer.Start(leth.blockchain) + leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, checkpoint, leth) + if leth.handler.ulc != nil { + log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.handler.ulc.keys), "minTrustedFraction", leth.handler.ulc.fraction) + leth.blockchain.DisableCheckFreq() + } // Rewind the chain in case of an incompatible config upgrade. if compat, ok := genesisErr.(*params.ConfigCompatError); ok { log.Warn("Rewinding chain to upgrade configuration", "err", compat) @@ -139,65 +141,26 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) } - leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay) - - if leth.protocolManager, err = NewProtocolManager( - leth.chainConfig, - light.DefaultClientIndexerConfig, - true, - config.NetworkId, - leth.eventMux, - leth.engine, - leth.peers, - leth.blockchain, - nil, - chainDb, - leth.odr, - leth.relay, - leth.serverPool, - quitSync, - &leth.wg, - config.ULC); err != nil { - return nil, err - } - - if leth.protocolManager.isULCEnabled() { - log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction) - leth.blockchain.DisableCheckFreq() - } - leth.ApiBackend = &LesApiBackend{leth, nil} - + leth.ApiBackend = &LesApiBackend{ctx.ExtRPCEnabled(), leth, nil} gpoParams := config.GPO if gpoParams.Default == nil { - gpoParams.Default = config.MinerGasPrice + gpoParams.Default = config.Miner.GasPrice } leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams) - return leth, nil -} -func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { - var name string - switch protocolVersion { - case lpv1: - name = "LES" - case lpv2: - name = "LES2" - default: - panic(nil) - } - return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) + return leth, nil } type LightDummyAPI struct{} // Etherbase is the address that mining rewards will be send to func (s *LightDummyAPI) Etherbase() (common.Address, error) { - return common.Address{}, fmt.Errorf("not supported") + return common.Address{}, fmt.Errorf("mining is not supported in light mode") } // Coinbase is the address that mining rewards will be send to (alias for Etherbase) func (s *LightDummyAPI) Coinbase() (common.Address, error) { - return common.Address{}, fmt.Errorf("not supported") + return common.Address{}, fmt.Errorf("mining is not supported in light mode") } // Hashrate returns the POW hashrate @@ -222,7 +185,7 @@ func (s *LightEthereum) APIs() []rpc.API { }, { Namespace: "eth", Version: "1.0", - Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), + Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), Public: true, }, { Namespace: "eth", @@ -234,6 +197,11 @@ func (s *LightEthereum) APIs() []rpc.API { Version: "1.0", Service: s.netRPCService, Public: true, + }, { + Namespace: "les", + Version: "1.0", + Service: NewPrivateLightAPI(&s.lesCommons), + Public: false, }, }...) } @@ -246,44 +214,63 @@ func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchai func (s *LightEthereum) TxPool() *light.TxPool { return s.txPool } func (s *LightEthereum) Engine() consensus.Engine { return s.engine } func (s *LightEthereum) LesVersion() int { return int(ClientProtocolVersions[0]) } -func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } +func (s *LightEthereum) Downloader() *downloader.Downloader { return s.handler.downloader } func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux } // Protocols implements node.Service, returning all the currently configured // network protocols to start. func (s *LightEthereum) Protocols() []p2p.Protocol { - return s.makeProtocols(ClientProtocolVersions) + return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { + if p := s.peers.Peer(peerIdToString(id)); p != nil { + return p.Info() + } + return nil + }) } // Start implements node.Service, starting all internal goroutines needed by the -// Ethereum protocol implementation. +// light ethereum protocol implementation. func (s *LightEthereum) Start(srvr *p2p.Server) error { log.Warn("Light client mode is an experimental feature") + + // Start bloom request workers. + s.wg.Add(bloomServiceThreads) s.startBloomHandlers(params.BloomBitsBlocksClient) - s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId) + + s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.config.NetworkId) + // clients are searching for the first advertised protocol in the list protocolVersion := AdvertiseProtocolVersions[0] s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion)) - s.protocolManager.Start(s.config.LightPeers) return nil } // Stop implements node.Service, terminating all internal goroutines used by the // Ethereum protocol. func (s *LightEthereum) Stop() error { + close(s.closeCh) + s.peers.Close() + s.reqDist.close() s.odr.Stop() + s.relay.Stop() s.bloomIndexer.Close() s.chtIndexer.Close() s.blockchain.Stop() - s.protocolManager.Stop() + s.handler.stop() s.txPool.Stop() s.engine.Close() - s.eventMux.Stop() - - time.Sleep(time.Millisecond * 200) + s.serverPool.stop() s.chainDb.Close() - close(s.shutdownChan) - + s.wg.Wait() + log.Info("Light ethereum stopped") return nil } + +// SetClient sets the rpc client and binds the registrar contract. +func (s *LightEthereum) SetContractBackend(backend bind.ContractBackend) { + if s.oracle == nil { + return + } + s.oracle.start(backend) +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/client_handler.go b/vendor/github.com/ethereum/go-ethereum/les/client_handler.go new file mode 100644 index 000000000..aff05ddbc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/client_handler.go @@ -0,0 +1,401 @@ +// Copyright 2019 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 les + +import ( + "math/big" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/params" +) + +// clientHandler is responsible for receiving and processing all incoming server +// responses. +type clientHandler struct { + ulc *ulc + checkpoint *params.TrustedCheckpoint + fetcher *lightFetcher + downloader *downloader.Downloader + backend *LightEthereum + + closeCh chan struct{} + wg sync.WaitGroup // WaitGroup used to track all connected peers. +} + +func newClientHandler(ulcServers []string, ulcFraction int, checkpoint *params.TrustedCheckpoint, backend *LightEthereum) *clientHandler { + handler := &clientHandler{ + backend: backend, + closeCh: make(chan struct{}), + } + if ulcServers != nil { + ulc, err := newULC(ulcServers, ulcFraction) + if err != nil { + log.Error("Failed to initialize ultra light client") + } + handler.ulc = ulc + log.Info("Enable ultra light client mode") + } + var height uint64 + if checkpoint != nil { + height = (checkpoint.SectionIndex+1)*params.CHTFrequency - 1 + } + handler.fetcher = newLightFetcher(handler) + handler.downloader = downloader.New(height, backend.chainDb, nil, backend.eventMux, nil, backend.blockchain, handler.removePeer) + handler.backend.peers.notify((*downloaderPeerNotify)(handler)) + return handler +} + +func (h *clientHandler) stop() { + close(h.closeCh) + h.downloader.Terminate() + h.fetcher.close() + h.wg.Wait() +} + +// runPeer is the p2p protocol run function for the given version. +func (h *clientHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { + trusted := false + if h.ulc != nil { + trusted = h.ulc.trusted(p.ID()) + } + peer := newPeer(int(version), h.backend.config.NetworkId, trusted, p, newMeteredMsgWriter(rw, int(version))) + peer.poolEntry = h.backend.serverPool.connect(peer, peer.Node()) + if peer.poolEntry == nil { + return p2p.DiscRequested + } + h.wg.Add(1) + defer h.wg.Done() + err := h.handle(peer) + h.backend.serverPool.disconnect(peer.poolEntry) + return err +} + +func (h *clientHandler) handle(p *peer) error { + if h.backend.peers.Len() >= h.backend.config.LightPeers && !p.Peer.Info().Network.Trusted { + return p2p.DiscTooManyPeers + } + p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) + + // Execute the LES handshake + var ( + head = h.backend.blockchain.CurrentHeader() + hash = head.Hash() + number = head.Number.Uint64() + td = h.backend.blockchain.GetTd(hash, number) + ) + if err := p.Handshake(td, hash, number, h.backend.blockchain.Genesis().Hash(), nil); err != nil { + p.Log().Debug("Light Ethereum handshake failed", "err", err) + return err + } + // Register the peer locally + if err := h.backend.peers.Register(p); err != nil { + p.Log().Error("Light Ethereum peer registration failed", "err", err) + return err + } + serverConnectionGauge.Update(int64(h.backend.peers.Len())) + + connectedAt := mclock.Now() + defer func() { + h.backend.peers.Unregister(p.id) + connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) + serverConnectionGauge.Update(int64(h.backend.peers.Len())) + }() + + h.fetcher.announce(p, p.headInfo) + + // pool entry can be nil during the unit test. + if p.poolEntry != nil { + h.backend.serverPool.registered(p.poolEntry) + } + // Spawn a main loop to handle all incoming messages. + for { + if err := h.handleMsg(p); err != nil { + p.Log().Debug("Light Ethereum message handling failed", "err", err) + p.fcServer.DumpLogs() + return err + } + } +} + +// handleMsg is invoked whenever an inbound message is received from a remote +// peer. The remote connection is torn down upon returning any error. +func (h *clientHandler) handleMsg(p *peer) error { + // Read the next message from the remote peer, and ensure it's fully consumed + msg, err := p.rw.ReadMsg() + if err != nil { + return err + } + p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) + + if msg.Size > ProtocolMaxMsgSize { + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + } + defer msg.Discard() + + var deliverMsg *Msg + + // Handle the message depending on its contents + switch msg.Code { + case AnnounceMsg: + p.Log().Trace("Received announce message") + var req announceData + if err := msg.Decode(&req); err != nil { + return errResp(ErrDecode, "%v: %v", msg, err) + } + if err := req.sanityCheck(); err != nil { + return err + } + update, size := req.Update.decode() + if p.rejectUpdate(size) { + return errResp(ErrRequestRejected, "") + } + p.updateFlowControl(update) + + if req.Hash != (common.Hash{}) { + if p.announceType == announceTypeNone { + return errResp(ErrUnexpectedResponse, "") + } + if p.announceType == announceTypeSigned { + if err := req.checkSignature(p.ID(), update); err != nil { + p.Log().Trace("Invalid announcement signature", "err", err) + return err + } + p.Log().Trace("Valid announcement signature") + } + p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) + h.fetcher.announce(p, &req) + } + case BlockHeadersMsg: + p.Log().Trace("Received block header response message") + var resp struct { + ReqID, BV uint64 + Headers []*types.Header + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + if h.fetcher.requestedID(resp.ReqID) { + h.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) + } else { + if err := h.downloader.DeliverHeaders(p.id, resp.Headers); err != nil { + log.Debug("Failed to deliver headers", "err", err) + } + } + case BlockBodiesMsg: + p.Log().Trace("Received block bodies response") + var resp struct { + ReqID, BV uint64 + Data []*types.Body + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgBlockBodies, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case CodeMsg: + p.Log().Trace("Received code response") + var resp struct { + ReqID, BV uint64 + Data [][]byte + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgCode, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case ReceiptsMsg: + p.Log().Trace("Received receipts response") + var resp struct { + ReqID, BV uint64 + Receipts []types.Receipts + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgReceipts, + ReqID: resp.ReqID, + Obj: resp.Receipts, + } + case ProofsV2Msg: + p.Log().Trace("Received les/2 proofs response") + var resp struct { + ReqID, BV uint64 + Data light.NodeList + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgProofsV2, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case HelperTrieProofsMsg: + p.Log().Trace("Received helper trie proof response") + var resp struct { + ReqID, BV uint64 + Data HelperTrieResps + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgHelperTrieProofs, + ReqID: resp.ReqID, + Obj: resp.Data, + } + case TxStatusMsg: + p.Log().Trace("Received tx status response") + var resp struct { + ReqID, BV uint64 + Status []light.TxStatus + } + if err := msg.Decode(&resp); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ReceivedReply(resp.ReqID, resp.BV) + deliverMsg = &Msg{ + MsgType: MsgTxStatus, + ReqID: resp.ReqID, + Obj: resp.Status, + } + case StopMsg: + p.freezeServer(true) + h.backend.retriever.frozen(p) + p.Log().Debug("Service stopped") + case ResumeMsg: + var bv uint64 + if err := msg.Decode(&bv); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + p.fcServer.ResumeFreeze(bv) + p.freezeServer(false) + p.Log().Debug("Service resumed") + default: + p.Log().Trace("Received invalid message", "code", msg.Code) + return errResp(ErrInvalidMsgCode, "%v", msg.Code) + } + // Deliver the received response to retriever. + if deliverMsg != nil { + if err := h.backend.retriever.deliver(p, deliverMsg); err != nil { + p.responseErrors++ + if p.responseErrors > maxResponseErrors { + return err + } + } + } + return nil +} + +func (h *clientHandler) removePeer(id string) { + h.backend.peers.Unregister(id) +} + +type peerConnection struct { + handler *clientHandler + peer *peer +} + +func (pc *peerConnection) Head() (common.Hash, *big.Int) { + return pc.peer.HeadAndTd() +} + +func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { + rq := &distReq{ + getCost: func(dp distPeer) uint64 { + peer := dp.(*peer) + return peer.GetRequestCost(GetBlockHeadersMsg, amount) + }, + canSend: func(dp distPeer) bool { + return dp.(*peer) == pc.peer + }, + request: func(dp distPeer) func() { + reqID := genReqID() + peer := dp.(*peer) + cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) + peer.fcServer.QueuedRequest(reqID, cost) + return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } + }, + } + _, ok := <-pc.handler.backend.reqDist.queue(rq) + if !ok { + return light.ErrNoPeers + } + return nil +} + +func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { + rq := &distReq{ + getCost: func(dp distPeer) uint64 { + peer := dp.(*peer) + return peer.GetRequestCost(GetBlockHeadersMsg, amount) + }, + canSend: func(dp distPeer) bool { + return dp.(*peer) == pc.peer + }, + request: func(dp distPeer) func() { + reqID := genReqID() + peer := dp.(*peer) + cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) + peer.fcServer.QueuedRequest(reqID, cost) + return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } + }, + } + _, ok := <-pc.handler.backend.reqDist.queue(rq) + if !ok { + return light.ErrNoPeers + } + return nil +} + +// downloaderPeerNotify implements peerSetNotify +type downloaderPeerNotify clientHandler + +func (d *downloaderPeerNotify) registerPeer(p *peer) { + h := (*clientHandler)(d) + pc := &peerConnection{ + handler: h, + peer: p, + } + h.downloader.RegisterLightPeer(p.id, ethVersion, pc) +} + +func (d *downloaderPeerNotify) unregisterPeer(p *peer) { + h := (*clientHandler)(d) + h.downloader.UnregisterPeer(p.id) +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/clientpool.go b/vendor/github.com/ethereum/go-ethereum/les/clientpool.go new file mode 100644 index 000000000..6773aab55 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/clientpool.go @@ -0,0 +1,609 @@ +// Copyright 2019 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 les + +import ( + "io" + "math" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/common/prque" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/rlp" +) + +const ( + negBalanceExpTC = time.Hour // time constant for exponentially reducing negative balance + fixedPointMultiplier = 0x1000000 // constant to convert logarithms to fixed point format + connectedBias = time.Minute * 5 // this bias is applied in favor of already connected clients in order to avoid kicking them out very soon + lazyQueueRefresh = time.Second * 10 // refresh period of the connected queue +) + +var ( + clientPoolDbKey = []byte("clientPool") + clientBalanceDbKey = []byte("clientPool-balance") +) + +// clientPool implements a client database that assigns a priority to each client +// based on a positive and negative balance. Positive balance is externally assigned +// to prioritized clients and is decreased with connection time and processed +// requests (unless the price factors are zero). If the positive balance is zero +// then negative balance is accumulated. Balance tracking and priority calculation +// for connected clients is done by balanceTracker. connectedQueue ensures that +// clients with the lowest positive or highest negative balance get evicted when +// the total capacity allowance is full and new clients with a better balance want +// to connect. Already connected nodes receive a small bias in their favor in order +// to avoid accepting and instantly kicking out clients. +// Balances of disconnected clients are stored in posBalanceQueue and negBalanceQueue +// and are also saved in the database. Negative balance is transformed into a +// logarithmic form with a constantly shifting linear offset in order to implement +// an exponential decrease. negBalanceQueue has a limited size and drops the smallest +// values when necessary. Positive balances are stored in the database as long as +// they exist, posBalanceQueue only acts as a cache for recently accessed entries. +type clientPool struct { + db ethdb.Database + lock sync.Mutex + clock mclock.Clock + stopCh chan chan struct{} + closed bool + removePeer func(enode.ID) + + queueLimit, countLimit int + freeClientCap, capacityLimit, connectedCapacity uint64 + + connectedMap map[enode.ID]*clientInfo + posBalanceMap map[enode.ID]*posBalance + negBalanceMap map[string]*negBalance + connectedQueue *prque.LazyQueue + posBalanceQueue, negBalanceQueue *prque.Prque + posFactors, negFactors priceFactors + posBalanceAccessCounter int64 + startupTime mclock.AbsTime + logOffsetAtStartup int64 +} + +// clientPeer represents a client in the pool. +// Positive balances are assigned to node key while negative balances are assigned +// to freeClientId. Currently network IP address without port is used because +// clients have a limited access to IP addresses while new node keys can be easily +// generated so it would be useless to assign a negative value to them. +type clientPeer interface { + ID() enode.ID + freeClientId() string + updateCapacity(uint64) +} + +// clientInfo represents a connected client +type clientInfo struct { + address string + id enode.ID + capacity uint64 + priority bool + pool *clientPool + peer clientPeer + queueIndex int // position in connectedQueue + balanceTracker balanceTracker +} + +// connSetIndex callback updates clientInfo item index in connectedQueue +func connSetIndex(a interface{}, index int) { + a.(*clientInfo).queueIndex = index +} + +// connPriority callback returns actual priority of clientInfo item in connectedQueue +func connPriority(a interface{}, now mclock.AbsTime) int64 { + c := a.(*clientInfo) + return c.balanceTracker.getPriority(now) +} + +// connMaxPriority callback returns estimated maximum priority of clientInfo item in connectedQueue +func connMaxPriority(a interface{}, until mclock.AbsTime) int64 { + c := a.(*clientInfo) + pri := c.balanceTracker.estimatedPriority(until, true) + c.balanceTracker.addCallback(balanceCallbackQueue, pri+1, func() { + c.pool.lock.Lock() + if c.queueIndex != -1 { + c.pool.connectedQueue.Update(c.queueIndex) + } + c.pool.lock.Unlock() + }) + return pri +} + +// priceFactors determine the pricing policy (may apply either to positive or +// negative balances which may have different factors). +// - timeFactor is cost unit per nanosecond of connection time +// - capacityFactor is cost unit per nanosecond of connection time per 1000000 capacity +// - requestFactor is cost unit per request "realCost" unit +type priceFactors struct { + timeFactor, capacityFactor, requestFactor float64 +} + +// newClientPool creates a new client pool +func newClientPool(db ethdb.Database, freeClientCap uint64, queueLimit int, clock mclock.Clock, removePeer func(enode.ID)) *clientPool { + pool := &clientPool{ + db: db, + clock: clock, + connectedMap: make(map[enode.ID]*clientInfo), + posBalanceMap: make(map[enode.ID]*posBalance), + negBalanceMap: make(map[string]*negBalance), + connectedQueue: prque.NewLazyQueue(connSetIndex, connPriority, connMaxPriority, clock, lazyQueueRefresh), + negBalanceQueue: prque.New(negSetIndex), + posBalanceQueue: prque.New(posSetIndex), + freeClientCap: freeClientCap, + queueLimit: queueLimit, + removePeer: removePeer, + stopCh: make(chan chan struct{}), + } + pool.loadFromDb() + go func() { + for { + select { + case <-clock.After(lazyQueueRefresh): + pool.lock.Lock() + pool.connectedQueue.Refresh() + pool.lock.Unlock() + case stop := <-pool.stopCh: + close(stop) + return + } + } + }() + return pool +} + +// stop shuts the client pool down +func (f *clientPool) stop() { + stop := make(chan struct{}) + f.stopCh <- stop + <-stop + f.lock.Lock() + f.closed = true + f.saveToDb() + f.lock.Unlock() +} + +// connect should be called after a successful handshake. If the connection was +// rejected, there is no need to call disconnect. +func (f *clientPool) connect(peer clientPeer, capacity uint64) bool { + f.lock.Lock() + defer f.lock.Unlock() + + // Short circuit is clientPool is already closed. + if f.closed { + return false + } + // Dedup connected peers. + id, freeID := peer.ID(), peer.freeClientId() + if _, ok := f.connectedMap[id]; ok { + clientRejectedMeter.Mark(1) + log.Debug("Client already connected", "address", freeID, "id", peerIdToString(id)) + return false + } + // Create a clientInfo but do not add it yet + now := f.clock.Now() + posBalance := f.getPosBalance(id).value + e := &clientInfo{pool: f, peer: peer, address: freeID, queueIndex: -1, id: id, priority: posBalance != 0} + + var negBalance uint64 + nb := f.negBalanceMap[freeID] + if nb != nil { + negBalance = uint64(math.Exp(float64(nb.logValue-f.logOffset(now)) / fixedPointMultiplier)) + } + // If the client is a free client, assign with a low free capacity, + // Otherwise assign with the given value(priority client) + if !e.priority { + capacity = f.freeClientCap + } + // Ensure the capacity will never lower than the free capacity. + if capacity < f.freeClientCap { + capacity = f.freeClientCap + } + e.capacity = capacity + + e.balanceTracker.init(f.clock, capacity) + e.balanceTracker.setBalance(posBalance, negBalance) + f.setClientPriceFactors(e) + + // If the number of clients already connected in the clientpool exceeds its + // capacity, evict some clients with lowest priority. + // + // If the priority of the newly added client is lower than the priority of + // all connected clients, the client is rejected. + newCapacity := f.connectedCapacity + capacity + newCount := f.connectedQueue.Size() + 1 + if newCapacity > f.capacityLimit || newCount > f.countLimit { + var ( + kickList []*clientInfo + kickPriority int64 + ) + f.connectedQueue.MultiPop(func(data interface{}, priority int64) bool { + c := data.(*clientInfo) + kickList = append(kickList, c) + kickPriority = priority + newCapacity -= c.capacity + newCount-- + return newCapacity > f.capacityLimit || newCount > f.countLimit + }) + if newCapacity > f.capacityLimit || newCount > f.countLimit || (e.balanceTracker.estimatedPriority(now+mclock.AbsTime(connectedBias), false)-kickPriority) > 0 { + // reject client + for _, c := range kickList { + f.connectedQueue.Push(c) + } + clientRejectedMeter.Mark(1) + log.Debug("Client rejected", "address", freeID, "id", peerIdToString(id)) + return false + } + // accept new client, drop old ones + for _, c := range kickList { + f.dropClient(c, now, true) + } + } + // client accepted, finish setting it up + if nb != nil { + delete(f.negBalanceMap, freeID) + f.negBalanceQueue.Remove(nb.queueIndex) + } + if e.priority { + e.balanceTracker.addCallback(balanceCallbackZero, 0, func() { f.balanceExhausted(id) }) + } + f.connectedMap[id] = e + f.connectedQueue.Push(e) + f.connectedCapacity += e.capacity + totalConnectedGauge.Update(int64(f.connectedCapacity)) + if e.capacity != f.freeClientCap { + e.peer.updateCapacity(e.capacity) + } + clientConnectedMeter.Mark(1) + log.Debug("Client accepted", "address", freeID) + return true +} + +// disconnect should be called when a connection is terminated. If the disconnection +// was initiated by the pool itself using disconnectFn then calling disconnect is +// not necessary but permitted. +func (f *clientPool) disconnect(p clientPeer) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.closed { + return + } + address := p.freeClientId() + id := p.ID() + // Short circuit if the peer hasn't been registered. + e := f.connectedMap[id] + if e == nil { + log.Debug("Client not connected", "address", address, "id", peerIdToString(id)) + return + } + f.dropClient(e, f.clock.Now(), false) +} + +// dropClient removes a client from the connected queue and finalizes its balance. +// If kick is true then it also initiates the disconnection. +func (f *clientPool) dropClient(e *clientInfo, now mclock.AbsTime, kick bool) { + if _, ok := f.connectedMap[e.id]; !ok { + return + } + f.finalizeBalance(e, now) + f.connectedQueue.Remove(e.queueIndex) + delete(f.connectedMap, e.id) + f.connectedCapacity -= e.capacity + totalConnectedGauge.Update(int64(f.connectedCapacity)) + if kick { + clientKickedMeter.Mark(1) + log.Debug("Client kicked out", "address", e.address) + f.removePeer(e.id) + } else { + clientDisconnectedMeter.Mark(1) + log.Debug("Client disconnected", "address", e.address) + } +} + +// finalizeBalance stops the balance tracker, retrieves the final balances and +// stores them in posBalanceQueue and negBalanceQueue +func (f *clientPool) finalizeBalance(c *clientInfo, now mclock.AbsTime) { + c.balanceTracker.stop(now) + pos, neg := c.balanceTracker.getBalance(now) + pb := f.getPosBalance(c.id) + pb.value = pos + f.storePosBalance(pb) + if neg < 1 { + neg = 1 + } + nb := &negBalance{address: c.address, queueIndex: -1, logValue: int64(math.Log(float64(neg))*fixedPointMultiplier) + f.logOffset(now)} + f.negBalanceMap[c.address] = nb + f.negBalanceQueue.Push(nb, -nb.logValue) + if f.negBalanceQueue.Size() > f.queueLimit { + nn := f.negBalanceQueue.PopItem().(*negBalance) + delete(f.negBalanceMap, nn.address) + } +} + +// balanceExhausted callback is called by balanceTracker when positive balance is exhausted. +// It revokes priority status and also reduces the client capacity if necessary. +func (f *clientPool) balanceExhausted(id enode.ID) { + f.lock.Lock() + defer f.lock.Unlock() + + c := f.connectedMap[id] + if c == nil || !c.priority { + return + } + c.priority = false + if c.capacity != f.freeClientCap { + f.connectedCapacity += f.freeClientCap - c.capacity + totalConnectedGauge.Update(int64(f.connectedCapacity)) + c.capacity = f.freeClientCap + c.peer.updateCapacity(c.capacity) + } +} + +// setConnLimit sets the maximum number and total capacity of connected clients, +// dropping some of them if necessary. +func (f *clientPool) setLimits(count int, totalCap uint64) { + f.lock.Lock() + defer f.lock.Unlock() + + f.countLimit = count + f.capacityLimit = totalCap + if f.connectedCapacity > f.capacityLimit || f.connectedQueue.Size() > f.countLimit { + now := mclock.Now() + f.connectedQueue.MultiPop(func(data interface{}, priority int64) bool { + c := data.(*clientInfo) + f.dropClient(c, now, true) + return f.connectedCapacity > f.capacityLimit || f.connectedQueue.Size() > f.countLimit + }) + } +} + +// requestCost feeds request cost after serving a request from the given peer. +func (f *clientPool) requestCost(p *peer, cost uint64) { + f.lock.Lock() + defer f.lock.Unlock() + + info, exist := f.connectedMap[p.ID()] + if !exist || f.closed { + return + } + info.balanceTracker.requestCost(cost) +} + +// logOffset calculates the time-dependent offset for the logarithmic +// representation of negative balance +func (f *clientPool) logOffset(now mclock.AbsTime) int64 { + // Note: fixedPointMultiplier acts as a multiplier here; the reason for dividing the divisor + // is to avoid int64 overflow. We assume that int64(negBalanceExpTC) >> fixedPointMultiplier. + logDecay := int64((time.Duration(now - f.startupTime)) / (negBalanceExpTC / fixedPointMultiplier)) + return f.logOffsetAtStartup + logDecay +} + +// setPriceFactors changes pricing factors for both positive and negative balances. +// Applies to connected clients and also future connections. +func (f *clientPool) setPriceFactors(posFactors, negFactors priceFactors) { + f.lock.Lock() + defer f.lock.Unlock() + + f.posFactors, f.negFactors = posFactors, negFactors + for _, c := range f.connectedMap { + f.setClientPriceFactors(c) + } +} + +// setClientPriceFactors sets the pricing factors for an individual connected client +func (f *clientPool) setClientPriceFactors(c *clientInfo) { + c.balanceTracker.setFactors(true, f.negFactors.timeFactor+float64(c.capacity)*f.negFactors.capacityFactor/1000000, f.negFactors.requestFactor) + c.balanceTracker.setFactors(false, f.posFactors.timeFactor+float64(c.capacity)*f.posFactors.capacityFactor/1000000, f.posFactors.requestFactor) +} + +// clientPoolStorage is the RLP representation of the pool's database storage +type clientPoolStorage struct { + LogOffset uint64 + List []*negBalance +} + +// loadFromDb restores pool status from the database storage +// (automatically called at initialization) +func (f *clientPool) loadFromDb() { + enc, err := f.db.Get(clientPoolDbKey) + if err != nil { + return + } + var storage clientPoolStorage + err = rlp.DecodeBytes(enc, &storage) + if err != nil { + log.Error("Failed to decode client list", "err", err) + return + } + f.logOffsetAtStartup = int64(storage.LogOffset) + f.startupTime = f.clock.Now() + for _, e := range storage.List { + log.Debug("Loaded free client record", "address", e.address, "logValue", e.logValue) + f.negBalanceMap[e.address] = e + f.negBalanceQueue.Push(e, -e.logValue) + } +} + +// saveToDb saves pool status to the database storage +// (automatically called during shutdown) +func (f *clientPool) saveToDb() { + now := f.clock.Now() + storage := clientPoolStorage{ + LogOffset: uint64(f.logOffset(now)), + } + for _, c := range f.connectedMap { + f.finalizeBalance(c, now) + } + i := 0 + storage.List = make([]*negBalance, len(f.negBalanceMap)) + for _, e := range f.negBalanceMap { + storage.List[i] = e + i++ + } + enc, err := rlp.EncodeToBytes(storage) + if err != nil { + log.Error("Failed to encode negative balance list", "err", err) + } else { + f.db.Put(clientPoolDbKey, enc) + } +} + +// storePosBalance stores a single positive balance entry in the database +func (f *clientPool) storePosBalance(b *posBalance) { + if b.value == b.lastStored { + return + } + enc, err := rlp.EncodeToBytes(b) + if err != nil { + log.Error("Failed to encode client balance", "err", err) + } else { + f.db.Put(append(clientBalanceDbKey, b.id[:]...), enc) + b.lastStored = b.value + } +} + +// getPosBalance retrieves a single positive balance entry from cache or the database +func (f *clientPool) getPosBalance(id enode.ID) *posBalance { + if b, ok := f.posBalanceMap[id]; ok { + f.posBalanceQueue.Remove(b.queueIndex) + f.posBalanceAccessCounter-- + f.posBalanceQueue.Push(b, f.posBalanceAccessCounter) + return b + } + balance := &posBalance{} + if enc, err := f.db.Get(append(clientBalanceDbKey, id[:]...)); err == nil { + if err := rlp.DecodeBytes(enc, balance); err != nil { + log.Error("Failed to decode client balance", "err", err) + balance = &posBalance{} + } + } + balance.id = id + balance.queueIndex = -1 + if f.posBalanceQueue.Size() >= f.queueLimit { + b := f.posBalanceQueue.PopItem().(*posBalance) + f.storePosBalance(b) + delete(f.posBalanceMap, b.id) + } + f.posBalanceAccessCounter-- + f.posBalanceQueue.Push(balance, f.posBalanceAccessCounter) + f.posBalanceMap[id] = balance + return balance +} + +// addBalance updates the positive balance of a client. +// If setTotal is false then the given amount is added to the balance. +// If setTotal is true then amount represents the total amount ever added to the +// given ID and positive balance is increased by (amount-lastTotal) while lastTotal +// is updated to amount. This method also allows removing positive balance. +func (f *clientPool) addBalance(id enode.ID, amount uint64, setTotal bool) { + f.lock.Lock() + defer f.lock.Unlock() + + pb := f.getPosBalance(id) + c := f.connectedMap[id] + var negBalance uint64 + if c != nil { + pb.value, negBalance = c.balanceTracker.getBalance(f.clock.Now()) + } + if setTotal { + if pb.value+amount > pb.lastTotal { + pb.value += amount - pb.lastTotal + } else { + pb.value = 0 + } + pb.lastTotal = amount + } else { + pb.value += amount + pb.lastTotal += amount + } + f.storePosBalance(pb) + if c != nil { + c.balanceTracker.setBalance(pb.value, negBalance) + if !c.priority && pb.value > 0 { + c.priority = true + c.balanceTracker.addCallback(balanceCallbackZero, 0, func() { f.balanceExhausted(id) }) + } + } +} + +// posBalance represents a recently accessed positive balance entry +type posBalance struct { + id enode.ID + value, lastStored, lastTotal uint64 + queueIndex int // position in posBalanceQueue +} + +// EncodeRLP implements rlp.Encoder +func (e *posBalance) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{e.value, e.lastTotal}) +} + +// DecodeRLP implements rlp.Decoder +func (e *posBalance) DecodeRLP(s *rlp.Stream) error { + var entry struct { + Value, LastTotal uint64 + } + if err := s.Decode(&entry); err != nil { + return err + } + e.value = entry.Value + e.lastStored = entry.Value + e.lastTotal = entry.LastTotal + return nil +} + +// posSetIndex callback updates posBalance item index in posBalanceQueue +func posSetIndex(a interface{}, index int) { + a.(*posBalance).queueIndex = index +} + +// negBalance represents a negative balance entry of a disconnected client +type negBalance struct { + address string + logValue int64 + queueIndex int // position in negBalanceQueue +} + +// EncodeRLP implements rlp.Encoder +func (e *negBalance) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{e.address, uint64(e.logValue)}) +} + +// DecodeRLP implements rlp.Decoder +func (e *negBalance) DecodeRLP(s *rlp.Stream) error { + var entry struct { + Address string + LogValue uint64 + } + if err := s.Decode(&entry); err != nil { + return err + } + e.address = entry.Address + e.logValue = int64(entry.LogValue) + e.queueIndex = -1 + return nil +} + +// negSetIndex callback updates negBalance item index in negBalanceQueue +func negSetIndex(a interface{}, index int) { + a.(*negBalance).queueIndex = index +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/commons.go b/vendor/github.com/ethereum/go-ethereum/les/commons.go index 21fb25714..ad3c5aef3 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/commons.go +++ b/vendor/github.com/ethereum/go-ethereum/les/commons.go @@ -19,24 +19,54 @@ package les import ( "fmt" "math/big" + "sync" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" ) +func errResp(code errCode, format string, v ...interface{}) error { + return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) +} + +func lesTopic(genesisHash common.Hash, protocolVersion uint) discv5.Topic { + var name string + switch protocolVersion { + case lpv2: + name = "LES2" + default: + panic(nil) + } + return discv5.Topic(name + "@" + common.Bytes2Hex(genesisHash.Bytes()[0:8])) +} + +type chainReader interface { + CurrentHeader() *types.Header +} + // lesCommons contains fields needed by both server and client. type lesCommons struct { + genesis common.Hash config *eth.Config + chainConfig *params.ChainConfig iConfig *light.IndexerConfig chainDb ethdb.Database - protocolManager *ProtocolManager + peers *peerSet + chainReader chainReader chtIndexer, bloomTrieIndexer *core.ChainIndexer + oracle *checkpointOracle + + closeCh chan struct{} + wg sync.WaitGroup } // NodeInfo represents a short summary of the Ethereum sub-protocol metadata @@ -51,7 +81,7 @@ type NodeInfo struct { } // makeProtocols creates protocol descriptors for the given LES versions. -func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { +func (c *lesCommons) makeProtocols(versions []uint, runPeer func(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error, peerInfo func(id enode.ID) interface{}) []p2p.Protocol { protos := make([]p2p.Protocol, len(versions)) for i, version := range versions { version := version @@ -60,15 +90,10 @@ func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { Version: version, Length: ProtocolLengths[version], NodeInfo: c.nodeInfo, - Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - return c.protocolManager.runPeer(version, p, rw) - }, - PeerInfo: func(id enode.ID) interface{} { - if p := c.protocolManager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil { - return p.Info() - } - return nil + Run: func(peer *p2p.Peer, rw p2p.MsgReadWriter) error { + return runPeer(version, peer, rw) }, + PeerInfo: peerInfo, } } return protos @@ -76,45 +101,46 @@ func (c *lesCommons) makeProtocols(versions []uint) []p2p.Protocol { // nodeInfo retrieves some protocol metadata about the running host node. func (c *lesCommons) nodeInfo() interface{} { - var cht params.TrustedCheckpoint - sections, _, _ := c.chtIndexer.Sections() - sections2, _, _ := c.bloomTrieIndexer.Sections() - - if !c.protocolManager.lightSync { - // convert to client section size if running in server mode - sections /= c.iConfig.PairChtSize / c.iConfig.ChtSize - } - - if sections2 < sections { - sections = sections2 - } - if sections > 0 { - sectionIndex := sections - 1 - sectionHead := c.bloomTrieIndexer.SectionHead(sectionIndex) - var chtRoot common.Hash - if c.protocolManager.lightSync { - chtRoot = light.GetChtRoot(c.chainDb, sectionIndex, sectionHead) - } else { - idxV2 := (sectionIndex+1)*c.iConfig.PairChtSize/c.iConfig.ChtSize - 1 - chtRoot = light.GetChtRoot(c.chainDb, idxV2, sectionHead) - } - cht = params.TrustedCheckpoint{ - SectionIndex: sectionIndex, - SectionHead: sectionHead, - CHTRoot: chtRoot, - BloomRoot: light.GetBloomTrieRoot(c.chainDb, sectionIndex, sectionHead), - } - } - - chain := c.protocolManager.blockchain - head := chain.CurrentHeader() + head := c.chainReader.CurrentHeader() hash := head.Hash() return &NodeInfo{ Network: c.config.NetworkId, - Difficulty: chain.GetTd(hash, head.Number.Uint64()), - Genesis: chain.Genesis().Hash(), - Config: chain.Config(), - Head: chain.CurrentHeader().Hash(), - CHT: cht, + Difficulty: rawdb.ReadTd(c.chainDb, hash, head.Number.Uint64()), + Genesis: c.genesis, + Config: c.chainConfig, + Head: hash, + CHT: c.latestLocalCheckpoint(), + } +} + +// latestLocalCheckpoint finds the common stored section index and returns a set +// of post-processed trie roots (CHT and BloomTrie) associated with the appropriate +// section index and head hash as a local checkpoint package. +func (c *lesCommons) latestLocalCheckpoint() params.TrustedCheckpoint { + sections, _, _ := c.chtIndexer.Sections() + sections2, _, _ := c.bloomTrieIndexer.Sections() + // Cap the section index if the two sections are not consistent. + if sections > sections2 { + sections = sections2 + } + if sections == 0 { + // No checkpoint information can be provided. + return params.TrustedCheckpoint{} + } + return c.localCheckpoint(sections - 1) +} + +// localCheckpoint returns a set of post-processed trie roots (CHT and BloomTrie) +// associated with the appropriate head hash by specific section index. +// +// The returned checkpoint is only the checkpoint generated by the local indexers, +// not the stable checkpoint registered in the registrar contract. +func (c *lesCommons) localCheckpoint(index uint64) params.TrustedCheckpoint { + sectionHead := c.chtIndexer.SectionHead(index) + return params.TrustedCheckpoint{ + SectionIndex: index, + SectionHead: sectionHead, + CHTRoot: light.GetChtRoot(c.chainDb, index, sectionHead), + BloomRoot: light.GetBloomTrieRoot(c.chainDb, index, sectionHead), } } diff --git a/vendor/github.com/ethereum/go-ethereum/les/costtracker.go b/vendor/github.com/ethereum/go-ethereum/les/costtracker.go new file mode 100644 index 000000000..81da04566 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/costtracker.go @@ -0,0 +1,516 @@ +// Copyright 2019 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 les + +import ( + "encoding/binary" + "math" + "sync" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/les/flowcontrol" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" +) + +const makeCostStats = false // make request cost statistics during operation + +var ( + // average request cost estimates based on serving time + reqAvgTimeCost = requestCostTable{ + GetBlockHeadersMsg: {150000, 30000}, + GetBlockBodiesMsg: {0, 700000}, + GetReceiptsMsg: {0, 1000000}, + GetCodeMsg: {0, 450000}, + GetProofsV2Msg: {0, 600000}, + GetHelperTrieProofsMsg: {0, 1000000}, + SendTxV2Msg: {0, 450000}, + GetTxStatusMsg: {0, 250000}, + } + // maximum incoming message size estimates + reqMaxInSize = requestCostTable{ + GetBlockHeadersMsg: {40, 0}, + GetBlockBodiesMsg: {0, 40}, + GetReceiptsMsg: {0, 40}, + GetCodeMsg: {0, 80}, + GetProofsV2Msg: {0, 80}, + GetHelperTrieProofsMsg: {0, 20}, + SendTxV2Msg: {0, 16500}, + GetTxStatusMsg: {0, 50}, + } + // maximum outgoing message size estimates + reqMaxOutSize = requestCostTable{ + GetBlockHeadersMsg: {0, 556}, + GetBlockBodiesMsg: {0, 100000}, + GetReceiptsMsg: {0, 200000}, + GetCodeMsg: {0, 50000}, + GetProofsV2Msg: {0, 4000}, + GetHelperTrieProofsMsg: {0, 4000}, + SendTxV2Msg: {0, 100}, + GetTxStatusMsg: {0, 100}, + } + // request amounts that have to fit into the minimum buffer size minBufferMultiplier times + minBufferReqAmount = map[uint64]uint64{ + GetBlockHeadersMsg: 192, + GetBlockBodiesMsg: 1, + GetReceiptsMsg: 1, + GetCodeMsg: 1, + GetProofsV2Msg: 1, + GetHelperTrieProofsMsg: 16, + SendTxV2Msg: 8, + GetTxStatusMsg: 64, + } + minBufferMultiplier = 3 +) + +const ( + maxCostFactor = 2 // ratio of maximum and average cost estimates + bufLimitRatio = 6000 // fixed bufLimit/MRR ratio + gfUsageThreshold = 0.5 + gfUsageTC = time.Second + gfRaiseTC = time.Second * 200 + gfDropTC = time.Second * 50 + gfDbKey = "_globalCostFactorV6" +) + +// costTracker is responsible for calculating costs and cost estimates on the +// server side. It continuously updates the global cost factor which is defined +// as the number of cost units per nanosecond of serving time in a single thread. +// It is based on statistics collected during serving requests in high-load periods +// and practically acts as a one-dimension request price scaling factor over the +// pre-defined cost estimate table. +// +// The reason for dynamically maintaining the global factor on the server side is: +// the estimated time cost of the request is fixed(hardcoded) but the configuration +// of the machine running the server is really different. Therefore, the request serving +// time in different machine will vary greatly. And also, the request serving time +// in same machine may vary greatly with different request pressure. +// +// In order to more effectively limit resources, we apply the global factor to serving +// time to make the result as close as possible to the estimated time cost no matter +// the server is slow or fast. And also we scale the totalRecharge with global factor +// so that fast server can serve more requests than estimation and slow server can +// reduce request pressure. +// +// Instead of scaling the cost values, the real value of cost units is changed by +// applying the factor to the serving times. This is more convenient because the +// changes in the cost factor can be applied immediately without always notifying +// the clients about the changed cost tables. +type costTracker struct { + db ethdb.Database + stopCh chan chan struct{} + + inSizeFactor float64 + outSizeFactor float64 + factor float64 + utilTarget float64 + minBufLimit uint64 + + gfLock sync.RWMutex + reqInfoCh chan reqInfo + totalRechargeCh chan uint64 + + stats map[uint64][]uint64 // Used for testing purpose. + + // TestHooks + testing bool // Disable real cost evaluation for testing purpose. + testCostList RequestCostList // Customized cost table for testing purpose. +} + +// newCostTracker creates a cost tracker and loads the cost factor statistics from the database. +// It also returns the minimum capacity that can be assigned to any peer. +func newCostTracker(db ethdb.Database, config *eth.Config) (*costTracker, uint64) { + utilTarget := float64(config.LightServ) * flowcontrol.FixedPointMultiplier / 100 + ct := &costTracker{ + db: db, + stopCh: make(chan chan struct{}), + reqInfoCh: make(chan reqInfo, 100), + utilTarget: utilTarget, + } + if config.LightIngress > 0 { + ct.inSizeFactor = utilTarget / float64(config.LightIngress) + } + if config.LightEgress > 0 { + ct.outSizeFactor = utilTarget / float64(config.LightEgress) + } + if makeCostStats { + ct.stats = make(map[uint64][]uint64) + for code := range reqAvgTimeCost { + ct.stats[code] = make([]uint64, 10) + } + } + ct.gfLoop() + costList := ct.makeCostList(ct.globalFactor() * 1.25) + for _, c := range costList { + amount := minBufferReqAmount[c.MsgCode] + cost := c.BaseCost + amount*c.ReqCost + if cost > ct.minBufLimit { + ct.minBufLimit = cost + } + } + ct.minBufLimit *= uint64(minBufferMultiplier) + return ct, (ct.minBufLimit-1)/bufLimitRatio + 1 +} + +// stop stops the cost tracker and saves the cost factor statistics to the database +func (ct *costTracker) stop() { + stopCh := make(chan struct{}) + ct.stopCh <- stopCh + <-stopCh + if makeCostStats { + ct.printStats() + } +} + +// makeCostList returns upper cost estimates based on the hardcoded cost estimate +// tables and the optionally specified incoming/outgoing bandwidth limits +func (ct *costTracker) makeCostList(globalFactor float64) RequestCostList { + maxCost := func(avgTimeCost, inSize, outSize uint64) uint64 { + cost := avgTimeCost * maxCostFactor + inSizeCost := uint64(float64(inSize) * ct.inSizeFactor * globalFactor) + if inSizeCost > cost { + cost = inSizeCost + } + outSizeCost := uint64(float64(outSize) * ct.outSizeFactor * globalFactor) + if outSizeCost > cost { + cost = outSizeCost + } + return cost + } + var list RequestCostList + for code, data := range reqAvgTimeCost { + baseCost := maxCost(data.baseCost, reqMaxInSize[code].baseCost, reqMaxOutSize[code].baseCost) + reqCost := maxCost(data.reqCost, reqMaxInSize[code].reqCost, reqMaxOutSize[code].reqCost) + if ct.minBufLimit != 0 { + // if minBufLimit is set then always enforce maximum request cost <= minBufLimit + maxCost := baseCost + reqCost*minBufferReqAmount[code] + if maxCost > ct.minBufLimit { + mul := 0.999 * float64(ct.minBufLimit) / float64(maxCost) + baseCost = uint64(float64(baseCost) * mul) + reqCost = uint64(float64(reqCost) * mul) + } + } + + list = append(list, requestCostListItem{ + MsgCode: code, + BaseCost: baseCost, + ReqCost: reqCost, + }) + } + return list +} + +// reqInfo contains the estimated time cost and the actual request serving time +// which acts as a feed source to update factor maintained by costTracker. +type reqInfo struct { + // avgTimeCost is the estimated time cost corresponding to maxCostTable. + avgTimeCost float64 + + // servingTime is the CPU time corresponding to the actual processing of + // the request. + servingTime float64 + + // msgCode indicates the type of request. + msgCode uint64 +} + +// gfLoop starts an event loop which updates the global cost factor which is +// calculated as a weighted average of the average estimate / serving time ratio. +// The applied weight equals the serving time if gfUsage is over a threshold, +// zero otherwise. gfUsage is the recent average serving time per time unit in +// an exponential moving window. This ensures that statistics are collected only +// under high-load circumstances where the measured serving times are relevant. +// The total recharge parameter of the flow control system which controls the +// total allowed serving time per second but nominated in cost units, should +// also be scaled with the cost factor and is also updated by this loop. +func (ct *costTracker) gfLoop() { + var ( + factor, totalRecharge float64 + gfLog, recentTime, recentAvg float64 + + lastUpdate, expUpdate = mclock.Now(), mclock.Now() + ) + + // Load historical cost factor statistics from the database. + data, _ := ct.db.Get([]byte(gfDbKey)) + if len(data) == 8 { + gfLog = math.Float64frombits(binary.BigEndian.Uint64(data[:])) + } + ct.factor = math.Exp(gfLog) + factor, totalRecharge = ct.factor, ct.utilTarget*ct.factor + + // In order to perform factor data statistics under the high request pressure, + // we only adjust factor when recent factor usage beyond the threshold. + threshold := gfUsageThreshold * float64(gfUsageTC) * ct.utilTarget / flowcontrol.FixedPointMultiplier + + go func() { + saveCostFactor := func() { + var data [8]byte + binary.BigEndian.PutUint64(data[:], math.Float64bits(gfLog)) + ct.db.Put([]byte(gfDbKey), data[:]) + log.Debug("global cost factor saved", "value", factor) + } + saveTicker := time.NewTicker(time.Minute * 10) + + for { + select { + case r := <-ct.reqInfoCh: + relCost := int64(factor * r.servingTime * 100 / r.avgTimeCost) // Convert the value to a percentage form + + // Record more metrics if we are debugging + if metrics.EnabledExpensive { + switch r.msgCode { + case GetBlockHeadersMsg: + relativeCostHeaderHistogram.Update(relCost) + case GetBlockBodiesMsg: + relativeCostBodyHistogram.Update(relCost) + case GetReceiptsMsg: + relativeCostReceiptHistogram.Update(relCost) + case GetCodeMsg: + relativeCostCodeHistogram.Update(relCost) + case GetProofsV2Msg: + relativeCostProofHistogram.Update(relCost) + case GetHelperTrieProofsMsg: + relativeCostHelperProofHistogram.Update(relCost) + case SendTxV2Msg: + relativeCostSendTxHistogram.Update(relCost) + case GetTxStatusMsg: + relativeCostTxStatusHistogram.Update(relCost) + } + } + // SendTxV2 and GetTxStatus requests are two special cases. + // All other requests will only put pressure on the database, and + // the corresponding delay is relatively stable. While these two + // requests involve txpool query, which is usually unstable. + // + // TODO(rjl493456442) fixes this. + if r.msgCode == SendTxV2Msg || r.msgCode == GetTxStatusMsg { + continue + } + requestServedMeter.Mark(int64(r.servingTime)) + requestServedTimer.Update(time.Duration(r.servingTime)) + requestEstimatedMeter.Mark(int64(r.avgTimeCost / factor)) + requestEstimatedTimer.Update(time.Duration(r.avgTimeCost / factor)) + relativeCostHistogram.Update(relCost) + + now := mclock.Now() + dt := float64(now - expUpdate) + expUpdate = now + exp := math.Exp(-dt / float64(gfUsageTC)) + + // calculate factor correction until now, based on previous values + var gfCorr float64 + max := recentTime + if recentAvg > max { + max = recentAvg + } + // we apply continuous correction when MAX(recentTime, recentAvg) > threshold + if max > threshold { + // calculate correction time between last expUpdate and now + if max*exp >= threshold { + gfCorr = dt + } else { + gfCorr = math.Log(max/threshold) * float64(gfUsageTC) + } + // calculate log(factor) correction with the right direction and time constant + if recentTime > recentAvg { + // drop factor if actual serving times are larger than average estimates + gfCorr /= -float64(gfDropTC) + } else { + // raise factor if actual serving times are smaller than average estimates + gfCorr /= float64(gfRaiseTC) + } + } + // update recent cost values with current request + recentTime = recentTime*exp + r.servingTime + recentAvg = recentAvg*exp + r.avgTimeCost/factor + + if gfCorr != 0 { + // Apply the correction to factor + gfLog += gfCorr + factor = math.Exp(gfLog) + // Notify outside modules the new factor and totalRecharge. + if time.Duration(now-lastUpdate) > time.Second { + totalRecharge, lastUpdate = ct.utilTarget*factor, now + ct.gfLock.Lock() + ct.factor = factor + ch := ct.totalRechargeCh + ct.gfLock.Unlock() + if ch != nil { + select { + case ct.totalRechargeCh <- uint64(totalRecharge): + default: + } + } + globalFactorGauge.Update(int64(1000 * factor)) + log.Debug("global cost factor updated", "factor", factor) + } + } + recentServedGauge.Update(int64(recentTime)) + recentEstimatedGauge.Update(int64(recentAvg)) + + case <-saveTicker.C: + saveCostFactor() + + case stopCh := <-ct.stopCh: + saveCostFactor() + close(stopCh) + return + } + } + }() +} + +// globalFactor returns the current value of the global cost factor +func (ct *costTracker) globalFactor() float64 { + ct.gfLock.RLock() + defer ct.gfLock.RUnlock() + + return ct.factor +} + +// totalRecharge returns the current total recharge parameter which is used by +// flowcontrol.ClientManager and is scaled by the global cost factor +func (ct *costTracker) totalRecharge() uint64 { + ct.gfLock.RLock() + defer ct.gfLock.RUnlock() + + return uint64(ct.factor * ct.utilTarget) +} + +// subscribeTotalRecharge returns all future updates to the total recharge value +// through a channel and also returns the current value +func (ct *costTracker) subscribeTotalRecharge(ch chan uint64) uint64 { + ct.gfLock.Lock() + defer ct.gfLock.Unlock() + + ct.totalRechargeCh = ch + return uint64(ct.factor * ct.utilTarget) +} + +// updateStats updates the global cost factor and (if enabled) the real cost vs. +// average estimate statistics +func (ct *costTracker) updateStats(code, amount, servingTime, realCost uint64) { + avg := reqAvgTimeCost[code] + avgTimeCost := avg.baseCost + amount*avg.reqCost + select { + case ct.reqInfoCh <- reqInfo{float64(avgTimeCost), float64(servingTime), code}: + default: + } + if makeCostStats { + realCost <<= 4 + l := 0 + for l < 9 && realCost > avgTimeCost { + l++ + realCost >>= 1 + } + atomic.AddUint64(&ct.stats[code][l], 1) + } +} + +// realCost calculates the final cost of a request based on actual serving time, +// incoming and outgoing message size +// +// Note: message size is only taken into account if bandwidth limitation is applied +// and the cost based on either message size is greater than the cost based on +// serving time. A maximum of the three costs is applied instead of their sum +// because the three limited resources (serving thread time and i/o bandwidth) can +// also be maxed out simultaneously. +func (ct *costTracker) realCost(servingTime uint64, inSize, outSize uint32) uint64 { + cost := float64(servingTime) + inSizeCost := float64(inSize) * ct.inSizeFactor + if inSizeCost > cost { + cost = inSizeCost + } + outSizeCost := float64(outSize) * ct.outSizeFactor + if outSizeCost > cost { + cost = outSizeCost + } + return uint64(cost * ct.globalFactor()) +} + +// printStats prints the distribution of real request cost relative to the average estimates +func (ct *costTracker) printStats() { + if ct.stats == nil { + return + } + for code, arr := range ct.stats { + log.Info("Request cost statistics", "code", code, "1/16", arr[0], "1/8", arr[1], "1/4", arr[2], "1/2", arr[3], "1", arr[4], "2", arr[5], "4", arr[6], "8", arr[7], "16", arr[8], ">16", arr[9]) + } +} + +type ( + // requestCostTable assigns a cost estimate function to each request type + // which is a linear function of the requested amount + // (cost = baseCost + reqCost * amount) + requestCostTable map[uint64]*requestCosts + requestCosts struct { + baseCost, reqCost uint64 + } + + // RequestCostList is a list representation of request costs which is used for + // database storage and communication through the network + RequestCostList []requestCostListItem + requestCostListItem struct { + MsgCode, BaseCost, ReqCost uint64 + } +) + +// getMaxCost calculates the estimated cost for a given request type and amount +func (table requestCostTable) getMaxCost(code, amount uint64) uint64 { + costs := table[code] + return costs.baseCost + amount*costs.reqCost +} + +// decode converts a cost list to a cost table +func (list RequestCostList) decode(protocolLength uint64) requestCostTable { + table := make(requestCostTable) + for _, e := range list { + if e.MsgCode < protocolLength { + table[e.MsgCode] = &requestCosts{ + baseCost: e.BaseCost, + reqCost: e.ReqCost, + } + } + } + return table +} + +// testCostList returns a dummy request cost list used by tests +func testCostList(testCost uint64) RequestCostList { + cl := make(RequestCostList, len(reqAvgTimeCost)) + var max uint64 + for code := range reqAvgTimeCost { + if code > max { + max = code + } + } + i := 0 + for code := uint64(0); code <= max; code++ { + if _, ok := reqAvgTimeCost[code]; ok { + cl[i].MsgCode = code + cl[i].BaseCost = testCost + cl[i].ReqCost = 0 + i++ + } + } + return cl +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/distributor.go b/vendor/github.com/ethereum/go-ethereum/les/distributor.go index f90765b62..62abef47d 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/distributor.go +++ b/vendor/github.com/ethereum/go-ethereum/les/distributor.go @@ -14,27 +14,31 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package light implements on-demand retrieval capable state and chain objects -// for the Ethereum Light Client. package les import ( "container/list" "sync" "time" + + "github.com/ethereum/go-ethereum/common/mclock" ) // requestDistributor implements a mechanism that distributes requests to // suitable peers, obeying flow control rules and prioritizing them in creation // order (even when a resend is necessary). type requestDistributor struct { - reqQueue *list.List - lastReqOrder uint64 - peers map[distPeer]struct{} - peerLock sync.RWMutex - stopChn, loopChn chan struct{} - loopNextSent bool - lock sync.Mutex + clock mclock.Clock + reqQueue *list.List + lastReqOrder uint64 + peers map[distPeer]struct{} + peerLock sync.RWMutex + loopChn chan struct{} + loopNextSent bool + lock sync.Mutex + + closeCh chan struct{} + wg sync.WaitGroup } // distPeer is an LES server peer interface for the request distributor. @@ -61,22 +65,26 @@ type distReq struct { canSend func(distPeer) bool request func(distPeer) func() - reqOrder uint64 - sentChn chan distPeer - element *list.Element + reqOrder uint64 + sentChn chan distPeer + element *list.Element + waitForPeers mclock.AbsTime + enterQueue mclock.AbsTime } // newRequestDistributor creates a new request distributor -func newRequestDistributor(peers *peerSet, stopChn chan struct{}) *requestDistributor { +func newRequestDistributor(peers *peerSet, clock mclock.Clock) *requestDistributor { d := &requestDistributor{ + clock: clock, reqQueue: list.New(), loopChn: make(chan struct{}, 2), - stopChn: stopChn, + closeCh: make(chan struct{}), peers: make(map[distPeer]struct{}), } if peers != nil { peers.notify(d) } + d.wg.Add(1) go d.loop() return d } @@ -104,13 +112,18 @@ func (d *requestDistributor) registerTestPeer(p distPeer) { // distMaxWait is the maximum waiting time after which further necessary waiting // times are recalculated based on new feedback from the servers -const distMaxWait = time.Millisecond * 10 +const distMaxWait = time.Millisecond * 50 + +// waitForPeers is the time window in which a request does not fail even if it +// has no suitable peers to send to at the moment +const waitForPeers = time.Second * 3 // main event loop func (d *requestDistributor) loop() { + defer d.wg.Done() for { select { - case <-d.stopChn: + case <-d.closeCh: d.lock.Lock() elem := d.reqQueue.Front() for elem != nil { @@ -133,6 +146,7 @@ func (d *requestDistributor) loop() { send := req.request(peer) if send != nil { peer.queueSend(send) + requestSendDelay.Update(time.Duration(d.clock.Now() - req.enterQueue)) } chn <- peer close(chn) @@ -148,7 +162,7 @@ func (d *requestDistributor) loop() { wait = distMaxWait } go func() { - time.Sleep(wait) + d.clock.Sleep(wait) d.loopChn <- struct{}{} }() break loop @@ -177,8 +191,6 @@ func (d *requestDistributor) nextRequest() (distPeer, *distReq, time.Duration) { checkedPeers := make(map[distPeer]struct{}) elem := d.reqQueue.Front() var ( - bestPeer distPeer - bestReq *distReq bestWait time.Duration sel *weightedRandomSelect ) @@ -186,9 +198,18 @@ func (d *requestDistributor) nextRequest() (distPeer, *distReq, time.Duration) { d.peerLock.RLock() defer d.peerLock.RUnlock() - for (len(d.peers) > 0 || elem == d.reqQueue.Front()) && elem != nil { + peerCount := len(d.peers) + for (len(checkedPeers) < peerCount || elem == d.reqQueue.Front()) && elem != nil { req := elem.Value.(*distReq) canSend := false + now := d.clock.Now() + if req.waitForPeers > now { + canSend = true + wait := time.Duration(req.waitForPeers - now) + if bestWait == 0 || wait < bestWait { + bestWait = wait + } + } for peer := range d.peers { if _, ok := checkedPeers[peer]; !ok && peer.canQueue() && req.canSend(peer) { canSend = true @@ -200,9 +221,7 @@ func (d *requestDistributor) nextRequest() (distPeer, *distReq, time.Duration) { } sel.update(selectPeerItem{peer: peer, req: req, weight: int64(bufRemain*1000000) + 1}) } else { - if bestReq == nil || wait < bestWait { - bestPeer = peer - bestReq = req + if bestWait == 0 || wait < bestWait { bestWait = wait } } @@ -221,7 +240,7 @@ func (d *requestDistributor) nextRequest() (distPeer, *distReq, time.Duration) { c := sel.choose().(selectPeerItem) return c.peer, c.req, 0 } - return bestPeer, bestReq, bestWait + return nil, nil, bestWait } // queue adds a request to the distribution queue, returns a channel where the @@ -235,7 +254,11 @@ func (d *requestDistributor) queue(r *distReq) chan distPeer { if r.reqOrder == 0 { d.lastReqOrder++ r.reqOrder = d.lastReqOrder + r.waitForPeers = d.clock.Now() + mclock.AbsTime(waitForPeers) } + // Assign the timestamp when the request is queued no matter it's + // a new one or re-queued one. + r.enterQueue = d.clock.Now() back := d.reqQueue.Back() if back == nil || r.reqOrder > back.Value.(*distReq).reqOrder { @@ -281,3 +304,8 @@ func (d *requestDistributor) remove(r *distReq) { r.element = nil } } + +func (d *requestDistributor) close() { + close(d.closeCh) + d.wg.Wait() +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/execqueue.go b/vendor/github.com/ethereum/go-ethereum/les/execqueue.go index 614721bf0..e0c88a990 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/execqueue.go +++ b/vendor/github.com/ethereum/go-ethereum/les/execqueue.go @@ -44,7 +44,7 @@ func (q *execQueue) loop() { func (q *execQueue) waitNext(drop bool) (f func()) { q.mu.Lock() - if drop { + if drop && len(q.funcs) > 0 { // Remove the function that just executed. We do this here instead of when // dequeuing so len(q.funcs) includes the function that is running. q.funcs = append(q.funcs[:0], q.funcs[1:]...) @@ -84,6 +84,13 @@ func (q *execQueue) queue(f func()) bool { return ok } +// clear drops all queued functions +func (q *execQueue) clear() { + q.mu.Lock() + q.funcs = q.funcs[:0] + q.mu.Unlock() +} + // quit stops the exec queue. // quit waits for the current execution to finish before returning. func (q *execQueue) quit() { diff --git a/vendor/github.com/ethereum/go-ethereum/les/fetcher.go b/vendor/github.com/ethereum/go-ethereum/les/fetcher.go index 56c96017e..df76c56d7 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/fetcher.go +++ b/vendor/github.com/ethereum/go-ethereum/les/fetcher.go @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( @@ -41,9 +40,8 @@ const ( // ODR system to ensure that we only request data related to a certain block from peers who have already processed // and announced that block. type lightFetcher struct { - pm *ProtocolManager - odr *LesOdr - chain lightChain + handler *clientHandler + chain *light.LightChain lock sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests maxConfirmedTd *big.Int @@ -56,15 +54,12 @@ type lightFetcher struct { requested map[uint64]fetchRequest deliverChn chan fetchResponse timeoutChn chan uint64 - requestChn chan bool // true if initiated from outside + requestTriggered bool + requestTrigger chan struct{} lastTrustedHeader *types.Header -} -// lightChain extends the BlockChain interface by locking. -type lightChain interface { - BlockChain - LockChain() - UnlockChain() + closeCh chan struct{} + wg sync.WaitGroup } // fetcherPeerInfo holds fetcher-specific information about each active peer @@ -114,53 +109,54 @@ type fetchResponse struct { } // newLightFetcher creates a new light fetcher -func newLightFetcher(pm *ProtocolManager) *lightFetcher { +func newLightFetcher(h *clientHandler) *lightFetcher { f := &lightFetcher{ - pm: pm, - chain: pm.blockchain.(*light.LightChain), - odr: pm.odr, + handler: h, + chain: h.backend.blockchain, peers: make(map[*peer]*fetcherPeerInfo), deliverChn: make(chan fetchResponse, 100), requested: make(map[uint64]fetchRequest), timeoutChn: make(chan uint64), - requestChn: make(chan bool, 100), + requestTrigger: make(chan struct{}, 1), syncDone: make(chan *peer), + closeCh: make(chan struct{}), maxConfirmedTd: big.NewInt(0), } - pm.peers.notify(f) + h.backend.peers.notify(f) - f.pm.wg.Add(1) + f.wg.Add(1) go f.syncLoop() return f } +func (f *lightFetcher) close() { + close(f.closeCh) + f.wg.Wait() +} + // syncLoop is the main event loop of the light fetcher func (f *lightFetcher) syncLoop() { - requesting := false - defer f.pm.wg.Done() + defer f.wg.Done() for { select { - case <-f.pm.quitSync: + case <-f.closeCh: return - // when a new announce is received, request loop keeps running until - // no further requests are necessary or possible - case newAnnounce := <-f.requestChn: + // request loop keeps running until no further requests are necessary or possible + case <-f.requestTrigger: f.lock.Lock() - s := requesting - requesting = false var ( rq *distReq reqID uint64 syncing bool ) - if !f.syncing && !(newAnnounce && s) { + if !f.syncing { rq, reqID, syncing = f.nextRequest() } + f.requestTriggered = rq != nil f.lock.Unlock() if rq != nil { - requesting = true - if _, ok := <-f.pm.reqDist.queue(rq); ok { + if _, ok := <-f.handler.backend.reqDist.queue(rq); ok { if syncing { f.lock.Lock() f.syncing = true @@ -176,11 +172,11 @@ func (f *lightFetcher) syncLoop() { } f.reqMu.Unlock() // keep starting new requests while possible - f.requestChn <- false + f.requestTrigger <- struct{}{} }() } } else { - f.requestChn <- false + f.requestTrigger <- struct{}{} } } case reqID := <-f.timeoutChn: @@ -191,9 +187,9 @@ func (f *lightFetcher) syncLoop() { } f.reqMu.Unlock() if ok { - f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true) + f.handler.backend.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), true) req.peer.Log().Debug("Fetching data timed out hard") - go f.pm.removePeer(req.peer.id) + go f.handler.removePeer(req.peer.id) } case resp := <-f.deliverChn: f.reqMu.Lock() @@ -206,24 +202,21 @@ func (f *lightFetcher) syncLoop() { } f.reqMu.Unlock() if ok { - f.pm.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout) + f.handler.backend.serverPool.adjustResponseTime(req.peer.poolEntry, time.Duration(mclock.Now()-req.sent), req.timeout) } f.lock.Lock() if !ok || !(f.syncing || f.processResponse(req, resp)) { resp.peer.Log().Debug("Failed processing response") - go f.pm.removePeer(resp.peer.id) + go f.handler.removePeer(resp.peer.id) } f.lock.Unlock() case p := <-f.syncDone: f.lock.Lock() p.Log().Debug("Done synchronising with peer") - res, h, td := f.checkSyncedHeaders(p) + f.checkSyncedHeaders(p) f.syncing = false - if res { - f.newHeaders([]*types.Header{h}, []*big.Int{td}) - } f.lock.Unlock() - f.requestChn <- false + f.requestTrigger <- struct{}{} // f.requestTriggered is always true here } } } @@ -271,7 +264,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) { if fp.lastAnnounced != nil && head.Td.Cmp(fp.lastAnnounced.td) <= 0 { // announced tds should be strictly monotonic p.Log().Debug("Received non-monotonic td", "current", head.Td, "previous", fp.lastAnnounced.td) - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) return } @@ -304,7 +297,7 @@ func (f *lightFetcher) announce(p *peer, head *announceData) { // if one of root's children is canonical, keep it, delete other branches and root itself var newRoot *fetcherTreeNode for i, nn := range fp.root.children { - if rawdb.ReadCanonicalHash(f.pm.chainDb, nn.number) == nn.hash { + if rawdb.ReadCanonicalHash(f.handler.backend.chainDb, nn.number) == nn.hash { fp.root.children = append(fp.root.children[:i], fp.root.children[i+1:]...) nn.parent = nil newRoot = nn @@ -357,7 +350,10 @@ func (f *lightFetcher) announce(p *peer, head *announceData) { fp.lastAnnounced = n p.lock.Unlock() f.checkUpdateStats(p, nil) - f.requestChn <- true + if !f.requestTriggered { + f.requestTriggered = true + f.requestTrigger <- struct{}{} + } } // peerHasBlock returns true if we can assume the peer knows the given block @@ -394,7 +390,7 @@ func (f *lightFetcher) peerHasBlock(p *peer, hash common.Hash, number uint64, ha // // when syncing, just check if it is part of the known chain, there is nothing better we // can do since we do not know the most recent block hash yet - return rawdb.ReadCanonicalHash(f.pm.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.pm.chainDb, number) == hash + return rawdb.ReadCanonicalHash(f.handler.backend.chainDb, fp.root.number) == fp.root.hash && rawdb.ReadCanonicalHash(f.handler.backend.chainDb, number) == hash } // requestAmount calculates the amount of headers to be downloaded starting @@ -429,7 +425,7 @@ func (f *lightFetcher) nextRequest() (*distReq, uint64, bool) { bestTd *big.Int bestSyncing bool ) - bestHash, bestAmount, bestTd, bestSyncing = f.findBestValues() + bestHash, bestAmount, bestTd, bestSyncing = f.findBestRequest() if bestTd == f.maxConfirmedTd { return nil, 0, false @@ -445,8 +441,10 @@ func (f *lightFetcher) nextRequest() (*distReq, uint64, bool) { return rq, reqID, bestSyncing } -// findBestValues retrieves the best values for LES or ULC mode. -func (f *lightFetcher) findBestValues() (bestHash common.Hash, bestAmount uint64, bestTd *big.Int, bestSyncing bool) { +// findBestRequest finds the best head to request that has been announced by but not yet requested from a known peer. +// It also returns the announced Td (which should be verified after fetching the head), +// the necessary amount to request and whether a downloader sync is necessary instead of a normal header request. +func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint64, bestTd *big.Int, bestSyncing bool) { bestTd = f.maxConfirmedTd bestSyncing = false @@ -455,8 +453,7 @@ func (f *lightFetcher) findBestValues() (bestHash common.Hash, bestAmount uint64 if f.checkKnownNode(p, n) || n.requested { continue } - - //if ulc mode is disabled, isTrustedHash returns true + // if ulc mode is disabled, isTrustedHash returns true amount := f.requestAmount(p, n) if (bestTd == nil || n.td.Cmp(bestTd) > 0 || amount < bestAmount) && (f.isTrustedHash(hash) || f.maxConfirmedTd.Int64() == 0) { bestHash = hash @@ -471,23 +468,18 @@ func (f *lightFetcher) findBestValues() (bestHash common.Hash, bestAmount uint64 // isTrustedHash checks if the block can be trusted by the minimum trusted fraction. func (f *lightFetcher) isTrustedHash(hash common.Hash) bool { - if !f.pm.isULCEnabled() { + // If ultra light cliet mode is disabled, trust all hashes + if f.handler.ulc == nil { return true } - - var numAgreed int - for p, fp := range f.peers { - if !p.isTrusted { - continue + // Ultra light enabled, only trust after enough confirmations + var agreed int + for peer, info := range f.peers { + if peer.trusted && info.nodeByHash[hash] != nil { + agreed++ } - if _, ok := fp.nodeByHash[hash]; !ok { - continue - } - - numAgreed++ } - - return 100*numAgreed/len(f.pm.ulc.trustedKeys) >= f.pm.ulc.minTrustedFraction + return 100*agreed/len(f.handler.ulc.keys) >= f.handler.ulc.fraction } func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { @@ -497,22 +489,24 @@ func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { }, canSend: func(dp distPeer) bool { p := dp.(*peer) - if p.isOnlyAnnounce { + f.lock.Lock() + defer f.lock.Unlock() + + if p.onlyAnnounce { return false } - fp := f.peers[p] return fp != nil && fp.nodeByHash[bestHash] != nil }, request: func(dp distPeer) func() { - if f.pm.isULCEnabled() { - //keep last trusted header before sync + if f.handler.ulc != nil { + // Keep last trusted header before sync f.setLastTrustedHeader(f.chain.CurrentHeader()) } go func() { p := dp.(*peer) p.Log().Debug("Synchronisation started") - f.pm.synchronise(p) + f.handler.synchronise(p) f.syncDone <- p }() return nil @@ -529,10 +523,12 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes }, canSend: func(dp distPeer) bool { p := dp.(*peer) - if p.isOnlyAnnounce { + f.lock.Lock() + defer f.lock.Unlock() + + if p.onlyAnnounce { return false } - fp := f.peers[p] if fp == nil { return false @@ -542,7 +538,7 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes }, request: func(dp distPeer) func() { p := dp.(*peer) - + f.lock.Lock() fp := f.peers[p] if fp != nil { n := fp.nodeByHash[bestHash] @@ -550,9 +546,10 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes n.requested = true } } + f.lock.Unlock() cost := p.GetRequestCost(GetBlockHeadersMsg, int(bestAmount)) - p.fcServer.QueueRequest(reqID, cost) + p.fcServer.QueuedRequest(reqID, cost) f.reqMu.Lock() f.requested[reqID] = fetchRequest{hash: bestHash, amount: bestAmount, peer: p, sent: mclock.Now()} f.reqMu.Unlock() @@ -609,7 +606,7 @@ func (f *lightFetcher) newHeaders(headers []*types.Header, tds []*big.Int) { for p, fp := range f.peers { if !f.checkAnnouncedHeaders(fp, headers, tds) { p.Log().Debug("Inconsistent announcement") - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) } if fp.confirmedTd != nil && (maxTd == nil || maxTd.Cmp(fp.confirmedTd) > 0) { maxTd = fp.confirmedTd @@ -697,43 +694,37 @@ func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*typ // checkSyncedHeaders updates peer's block tree after synchronisation by marking // downloaded headers as known. If none of the announced headers are found after // syncing, the peer is dropped. -func (f *lightFetcher) checkSyncedHeaders(p *peer) (bool, *types.Header, *big.Int) { +func (f *lightFetcher) checkSyncedHeaders(p *peer) { fp := f.peers[p] if fp == nil { p.Log().Debug("Unknown peer to check sync headers") - return false, nil, nil + return } - - n := fp.lastAnnounced - var td *big.Int - - var h *types.Header - if f.pm.isULCEnabled() { - var unapprovedHashes []common.Hash - // Overwrite last announced for ULC mode - h, unapprovedHashes = f.lastTrustedTreeNode(p) - //rollback untrusted blocks - f.chain.Rollback(unapprovedHashes) - //overwrite to last trusted - n = fp.nodeByHash[h.Hash()] + var ( + node = fp.lastAnnounced + td *big.Int + ) + if f.handler.ulc != nil { + // Roll back untrusted blocks + h, unapproved := f.lastTrustedTreeNode(p) + f.chain.Rollback(unapproved) + node = fp.nodeByHash[h.Hash()] } - - //find last valid block - for n != nil { - if td = f.chain.GetTd(n.hash, n.number); td != nil { + // Find last valid block + for node != nil { + if td = f.chain.GetTd(node.hash, node.number); td != nil { break } - n = n.parent + node = node.parent } - - // Now n is the latest downloaded/approved header after syncing - if n == nil { + // Now node is the latest downloaded/approved header after syncing + if node == nil { p.Log().Debug("Synchronisation failed") - go f.pm.removePeer(p.id) - return false, nil, nil + go f.handler.removePeer(p.id) + return } - header := f.chain.GetHeader(n.hash, n.number) - return true, header, td + header := f.chain.GetHeader(node.hash, node.number) + f.newHeaders([]*types.Header{header}, []*big.Int{td}) } // lastTrustedTreeNode return last approved treeNode and a list of unapproved hashes @@ -749,13 +740,13 @@ func (f *lightFetcher) lastTrustedTreeNode(p *peer) (*types.Header, []common.Has if canonical.Number.Uint64() > f.lastTrustedHeader.Number.Uint64() { canonical = f.chain.GetHeaderByNumber(f.lastTrustedHeader.Number.Uint64()) } - commonAncestor := rawdb.FindCommonAncestor(f.pm.chainDb, canonical, f.lastTrustedHeader) + commonAncestor := rawdb.FindCommonAncestor(f.handler.backend.chainDb, canonical, f.lastTrustedHeader) if commonAncestor == nil { log.Error("Common ancestor of last trusted header and canonical header is nil", "canonical hash", canonical.Hash(), "trusted hash", f.lastTrustedHeader.Hash()) return current, unapprovedHashes } - for !f.isStopValidationTree(current, commonAncestor) { + for current.Hash() == commonAncestor.Hash() { if f.isTrustedHash(current.Hash()) { break } @@ -765,28 +756,6 @@ func (f *lightFetcher) lastTrustedTreeNode(p *peer) (*types.Header, []common.Has return current, unapprovedHashes } -//isStopValidationTree found when we should stop on finding last trusted header -func (f *lightFetcher) isStopValidationTree(current *types.Header, commonAncestor *types.Header) bool { - if current == nil { - return true - } - - currentHash := current.Hash() - ancestorHash := commonAncestor.Hash() - - //found lastTrustedHeader - if currentHash == f.lastTrustedHeader.Hash() { - return true - } - - //found common ancestor between lastTrustedHeader and - if current.Hash() == ancestorHash { - return true - } - - return false -} - func (f *lightFetcher) setLastTrustedHeader(h *types.Header) { f.lock.Lock() defer f.lock.Unlock() @@ -817,7 +786,7 @@ func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool { } if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) { p.Log().Debug("Inconsistent announcement") - go f.pm.removePeer(p.id) + go f.handler.removePeer(p.id) } if fp.confirmedTd != nil { f.updateMaxConfirmedTd(fp.confirmedTd) @@ -910,12 +879,12 @@ func (f *lightFetcher) checkUpdateStats(p *peer, newEntry *updateStatsEntry) { fp.firstUpdateStats = newEntry } for fp.firstUpdateStats != nil && fp.firstUpdateStats.time <= now-mclock.AbsTime(blockDelayTimeout) { - f.pm.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout) + f.handler.backend.serverPool.adjustBlockDelay(p.poolEntry, blockDelayTimeout) fp.firstUpdateStats = fp.firstUpdateStats.next } if fp.confirmedTd != nil { for fp.firstUpdateStats != nil && fp.firstUpdateStats.td.Cmp(fp.confirmedTd) <= 0 { - f.pm.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time)) + f.handler.backend.serverPool.adjustBlockDelay(p.poolEntry, time.Duration(now-fp.firstUpdateStats.time)) fp.firstUpdateStats = fp.firstUpdateStats.next } } diff --git a/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/control.go b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/control.go index 8ef4ba511..490013677 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/control.go +++ b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/control.go @@ -18,166 +18,412 @@ package flowcontrol import ( + "fmt" "sync" "time" "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/log" ) -const fcTimeConst = time.Millisecond +const ( + // fcTimeConst is the time constant applied for MinRecharge during linear + // buffer recharge period + fcTimeConst = time.Millisecond + // DecParamDelay is applied at server side when decreasing capacity in order to + // avoid a buffer underrun error due to requests sent by the client before + // receiving the capacity update announcement + DecParamDelay = time.Second * 2 + // keepLogs is the duration of keeping logs; logging is not used if zero + keepLogs = 0 +) +// ServerParams are the flow control parameters specified by a server for a client +// +// Note: a server can assign different amounts of capacity to each client by giving +// different parameters to them. type ServerParams struct { BufLimit, MinRecharge uint64 } -type ClientNode struct { - params *ServerParams - bufValue uint64 - lastTime mclock.AbsTime - lock sync.Mutex - cm *ClientManager - cmNode *cmNode +// scheduledUpdate represents a delayed flow control parameter update +type scheduledUpdate struct { + time mclock.AbsTime + params ServerParams } -func NewClientNode(cm *ClientManager, params *ServerParams) *ClientNode { +// ClientNode is the flow control system's representation of a client +// (used in server mode only) +type ClientNode struct { + params ServerParams + bufValue int64 + lastTime mclock.AbsTime + updateSchedule []scheduledUpdate + sumCost uint64 // sum of req costs received from this client + accepted map[uint64]uint64 // value = sumCost after accepting the given req + connected bool + lock sync.Mutex + cm *ClientManager + log *logger + cmNodeFields +} + +// NewClientNode returns a new ClientNode +func NewClientNode(cm *ClientManager, params ServerParams) *ClientNode { node := &ClientNode{ - cm: cm, - params: params, - bufValue: params.BufLimit, - lastTime: mclock.Now(), + cm: cm, + params: params, + bufValue: int64(params.BufLimit), + lastTime: cm.clock.Now(), + accepted: make(map[uint64]uint64), + connected: true, } - node.cmNode = cm.addNode(node) + if keepLogs > 0 { + node.log = newLogger(keepLogs) + } + cm.connect(node) return node } -func (peer *ClientNode) Remove(cm *ClientManager) { - cm.removeNode(peer.cmNode) +// Disconnect should be called when a client is disconnected +func (node *ClientNode) Disconnect() { + node.lock.Lock() + defer node.lock.Unlock() + + node.connected = false + node.cm.disconnect(node) } -func (peer *ClientNode) recalcBV(time mclock.AbsTime) { - dt := uint64(time - peer.lastTime) - if time < peer.lastTime { +// BufferStatus returns the current buffer value and limit +func (node *ClientNode) BufferStatus() (uint64, uint64) { + node.lock.Lock() + defer node.lock.Unlock() + + if !node.connected { + return 0, 0 + } + now := node.cm.clock.Now() + node.update(now) + node.cm.updateBuffer(node, 0, now) + bv := node.bufValue + if bv < 0 { + bv = 0 + } + return uint64(bv), node.params.BufLimit +} + +// OneTimeCost subtracts the given amount from the node's buffer. +// +// Note: this call can take the buffer into the negative region internally. +// In this case zero buffer value is returned by exported calls and no requests +// are accepted. +func (node *ClientNode) OneTimeCost(cost uint64) { + node.lock.Lock() + defer node.lock.Unlock() + + now := node.cm.clock.Now() + node.update(now) + node.bufValue -= int64(cost) + node.cm.updateBuffer(node, -int64(cost), now) +} + +// Freeze notifies the client manager about a client freeze event in which case +// the total capacity allowance is slightly reduced. +func (node *ClientNode) Freeze() { + node.lock.Lock() + frozenCap := node.params.MinRecharge + node.lock.Unlock() + node.cm.reduceTotalCapacity(frozenCap) +} + +// update recalculates the buffer value at a specified time while also performing +// scheduled flow control parameter updates if necessary +func (node *ClientNode) update(now mclock.AbsTime) { + for len(node.updateSchedule) > 0 && node.updateSchedule[0].time <= now { + node.recalcBV(node.updateSchedule[0].time) + node.updateParams(node.updateSchedule[0].params, now) + node.updateSchedule = node.updateSchedule[1:] + } + node.recalcBV(now) +} + +// recalcBV recalculates the buffer value at a specified time +func (node *ClientNode) recalcBV(now mclock.AbsTime) { + dt := uint64(now - node.lastTime) + if now < node.lastTime { dt = 0 } - peer.bufValue += peer.params.MinRecharge * dt / uint64(fcTimeConst) - if peer.bufValue > peer.params.BufLimit { - peer.bufValue = peer.params.BufLimit + node.bufValue += int64(node.params.MinRecharge * dt / uint64(fcTimeConst)) + if node.bufValue > int64(node.params.BufLimit) { + node.bufValue = int64(node.params.BufLimit) } - peer.lastTime = time + if node.log != nil { + node.log.add(now, fmt.Sprintf("updated bv=%d MRR=%d BufLimit=%d", node.bufValue, node.params.MinRecharge, node.params.BufLimit)) + } + node.lastTime = now } -func (peer *ClientNode) AcceptRequest() (uint64, bool) { - peer.lock.Lock() - defer peer.lock.Unlock() +// UpdateParams updates the flow control parameters of a client node +func (node *ClientNode) UpdateParams(params ServerParams) { + node.lock.Lock() + defer node.lock.Unlock() - time := mclock.Now() - peer.recalcBV(time) - return peer.bufValue, peer.cm.accept(peer.cmNode, time) -} - -func (peer *ClientNode) RequestProcessed(cost uint64) (bv, realCost uint64) { - peer.lock.Lock() - defer peer.lock.Unlock() - - time := mclock.Now() - peer.recalcBV(time) - peer.bufValue -= cost - rcValue, rcost := peer.cm.processed(peer.cmNode, time) - if rcValue < peer.params.BufLimit { - bv := peer.params.BufLimit - rcValue - if bv > peer.bufValue { - peer.bufValue = bv + now := node.cm.clock.Now() + node.update(now) + if params.MinRecharge >= node.params.MinRecharge { + node.updateSchedule = nil + node.updateParams(params, now) + } else { + for i, s := range node.updateSchedule { + if params.MinRecharge >= s.params.MinRecharge { + s.params = params + node.updateSchedule = node.updateSchedule[:i+1] + return + } } + node.updateSchedule = append(node.updateSchedule, scheduledUpdate{time: now + mclock.AbsTime(DecParamDelay), params: params}) } - return peer.bufValue, rcost } +// updateParams updates the flow control parameters of the node +func (node *ClientNode) updateParams(params ServerParams, now mclock.AbsTime) { + diff := int64(params.BufLimit - node.params.BufLimit) + if diff > 0 { + node.bufValue += diff + } else if node.bufValue > int64(params.BufLimit) { + node.bufValue = int64(params.BufLimit) + } + node.cm.updateParams(node, params, now) +} + +// AcceptRequest returns whether a new request can be accepted and the missing +// buffer amount if it was rejected due to a buffer underrun. If accepted, maxCost +// is deducted from the flow control buffer. +func (node *ClientNode) AcceptRequest(reqID, index, maxCost uint64) (accepted bool, bufShort uint64, priority int64) { + node.lock.Lock() + defer node.lock.Unlock() + + now := node.cm.clock.Now() + node.update(now) + if int64(maxCost) > node.bufValue { + if node.log != nil { + node.log.add(now, fmt.Sprintf("rejected reqID=%d bv=%d maxCost=%d", reqID, node.bufValue, maxCost)) + node.log.dump(now) + } + return false, maxCost - uint64(node.bufValue), 0 + } + node.bufValue -= int64(maxCost) + node.sumCost += maxCost + if node.log != nil { + node.log.add(now, fmt.Sprintf("accepted reqID=%d bv=%d maxCost=%d sumCost=%d", reqID, node.bufValue, maxCost, node.sumCost)) + } + node.accepted[index] = node.sumCost + return true, 0, node.cm.accepted(node, maxCost, now) +} + +// RequestProcessed should be called when the request has been processed +func (node *ClientNode) RequestProcessed(reqID, index, maxCost, realCost uint64) uint64 { + node.lock.Lock() + defer node.lock.Unlock() + + now := node.cm.clock.Now() + node.update(now) + node.cm.processed(node, maxCost, realCost, now) + bv := node.bufValue + int64(node.sumCost-node.accepted[index]) + if node.log != nil { + node.log.add(now, fmt.Sprintf("processed reqID=%d bv=%d maxCost=%d realCost=%d sumCost=%d oldSumCost=%d reportedBV=%d", reqID, node.bufValue, maxCost, realCost, node.sumCost, node.accepted[index], bv)) + } + delete(node.accepted, index) + if bv < 0 { + return 0 + } + return uint64(bv) +} + +// ServerNode is the flow control system's representation of a server +// (used in client mode only) type ServerNode struct { + clock mclock.Clock bufEstimate uint64 + bufRecharge bool lastTime mclock.AbsTime - params *ServerParams + params ServerParams sumCost uint64 // sum of req costs sent to this server pending map[uint64]uint64 // value = sumCost after sending the given req + log *logger lock sync.RWMutex } -func NewServerNode(params *ServerParams) *ServerNode { - return &ServerNode{ +// NewServerNode returns a new ServerNode +func NewServerNode(params ServerParams, clock mclock.Clock) *ServerNode { + node := &ServerNode{ + clock: clock, bufEstimate: params.BufLimit, - lastTime: mclock.Now(), + bufRecharge: false, + lastTime: clock.Now(), params: params, pending: make(map[uint64]uint64), } + if keepLogs > 0 { + node.log = newLogger(keepLogs) + } + return node } -func (peer *ServerNode) recalcBLE(time mclock.AbsTime) { - dt := uint64(time - peer.lastTime) - if time < peer.lastTime { - dt = 0 +// UpdateParams updates the flow control parameters of the node +func (node *ServerNode) UpdateParams(params ServerParams) { + node.lock.Lock() + defer node.lock.Unlock() + + node.recalcBLE(mclock.Now()) + if params.BufLimit > node.params.BufLimit { + node.bufEstimate += params.BufLimit - node.params.BufLimit + } else { + if node.bufEstimate > params.BufLimit { + node.bufEstimate = params.BufLimit + } } - peer.bufEstimate += peer.params.MinRecharge * dt / uint64(fcTimeConst) - if peer.bufEstimate > peer.params.BufLimit { - peer.bufEstimate = peer.params.BufLimit + node.params = params +} + +// recalcBLE recalculates the lowest estimate for the client's buffer value at +// the given server at the specified time +func (node *ServerNode) recalcBLE(now mclock.AbsTime) { + if now < node.lastTime { + return + } + if node.bufRecharge { + dt := uint64(now - node.lastTime) + node.bufEstimate += node.params.MinRecharge * dt / uint64(fcTimeConst) + if node.bufEstimate >= node.params.BufLimit { + node.bufEstimate = node.params.BufLimit + node.bufRecharge = false + } + } + node.lastTime = now + if node.log != nil { + node.log.add(now, fmt.Sprintf("updated bufEst=%d MRR=%d BufLimit=%d", node.bufEstimate, node.params.MinRecharge, node.params.BufLimit)) } - peer.lastTime = time } // safetyMargin is added to the flow control waiting time when estimated buffer value is low const safetyMargin = time.Millisecond -func (peer *ServerNode) canSend(maxCost uint64) (time.Duration, float64) { - peer.recalcBLE(mclock.Now()) - maxCost += uint64(safetyMargin) * peer.params.MinRecharge / uint64(fcTimeConst) - if maxCost > peer.params.BufLimit { - maxCost = peer.params.BufLimit - } - if peer.bufEstimate >= maxCost { - return 0, float64(peer.bufEstimate-maxCost) / float64(peer.params.BufLimit) - } - return time.Duration((maxCost - peer.bufEstimate) * uint64(fcTimeConst) / peer.params.MinRecharge), 0 -} - // CanSend returns the minimum waiting time required before sending a request // with the given maximum estimated cost. Second return value is the relative // estimated buffer level after sending the request (divided by BufLimit). -func (peer *ServerNode) CanSend(maxCost uint64) (time.Duration, float64) { - peer.lock.RLock() - defer peer.lock.RUnlock() +func (node *ServerNode) CanSend(maxCost uint64) (time.Duration, float64) { + node.lock.RLock() + defer node.lock.RUnlock() - return peer.canSend(maxCost) -} - -// QueueRequest should be called when the request has been assigned to the given -// server node, before putting it in the send queue. It is mandatory that requests -// are sent in the same order as the QueueRequest calls are made. -func (peer *ServerNode) QueueRequest(reqID, maxCost uint64) { - peer.lock.Lock() - defer peer.lock.Unlock() - - peer.bufEstimate -= maxCost - peer.sumCost += maxCost - peer.pending[reqID] = peer.sumCost -} - -// GotReply adjusts estimated buffer value according to the value included in -// the latest request reply. -func (peer *ServerNode) GotReply(reqID, bv uint64) { - - peer.lock.Lock() - defer peer.lock.Unlock() - - if bv > peer.params.BufLimit { - bv = peer.params.BufLimit + now := node.clock.Now() + node.recalcBLE(now) + maxCost += uint64(safetyMargin) * node.params.MinRecharge / uint64(fcTimeConst) + if maxCost > node.params.BufLimit { + maxCost = node.params.BufLimit } - sc, ok := peer.pending[reqID] + if node.bufEstimate >= maxCost { + relBuf := float64(node.bufEstimate-maxCost) / float64(node.params.BufLimit) + if node.log != nil { + node.log.add(now, fmt.Sprintf("canSend bufEst=%d maxCost=%d true relBuf=%f", node.bufEstimate, maxCost, relBuf)) + } + return 0, relBuf + } + timeLeft := time.Duration((maxCost - node.bufEstimate) * uint64(fcTimeConst) / node.params.MinRecharge) + if node.log != nil { + node.log.add(now, fmt.Sprintf("canSend bufEst=%d maxCost=%d false timeLeft=%v", node.bufEstimate, maxCost, timeLeft)) + } + return timeLeft, 0 +} + +// QueuedRequest should be called when the request has been assigned to the given +// server node, before putting it in the send queue. It is mandatory that requests +// are sent in the same order as the QueuedRequest calls are made. +func (node *ServerNode) QueuedRequest(reqID, maxCost uint64) { + node.lock.Lock() + defer node.lock.Unlock() + + now := node.clock.Now() + node.recalcBLE(now) + // Note: we do not know when requests actually arrive to the server so bufRecharge + // is not turned on here if buffer was full; in this case it is going to be turned + // on by the first reply's bufValue feedback + if node.bufEstimate >= maxCost { + node.bufEstimate -= maxCost + } else { + log.Error("Queued request with insufficient buffer estimate") + node.bufEstimate = 0 + } + node.sumCost += maxCost + node.pending[reqID] = node.sumCost + if node.log != nil { + node.log.add(now, fmt.Sprintf("queued reqID=%d bufEst=%d maxCost=%d sumCost=%d", reqID, node.bufEstimate, maxCost, node.sumCost)) + } +} + +// ReceivedReply adjusts estimated buffer value according to the value included in +// the latest request reply. +func (node *ServerNode) ReceivedReply(reqID, bv uint64) { + node.lock.Lock() + defer node.lock.Unlock() + + now := node.clock.Now() + node.recalcBLE(now) + if bv > node.params.BufLimit { + bv = node.params.BufLimit + } + sc, ok := node.pending[reqID] if !ok { return } - delete(peer.pending, reqID) - cc := peer.sumCost - sc - peer.bufEstimate = 0 + delete(node.pending, reqID) + cc := node.sumCost - sc + newEstimate := uint64(0) if bv > cc { - peer.bufEstimate = bv - cc + newEstimate = bv - cc + } + if newEstimate > node.bufEstimate { + // Note: we never reduce the buffer estimate based on the reported value because + // this can only happen because of the delayed delivery of the latest reply. + // The lowest estimate based on the previous reply can still be considered valid. + node.bufEstimate = newEstimate + } + + node.bufRecharge = node.bufEstimate < node.params.BufLimit + node.lastTime = now + if node.log != nil { + node.log.add(now, fmt.Sprintf("received reqID=%d bufEst=%d reportedBv=%d sumCost=%d oldSumCost=%d", reqID, node.bufEstimate, bv, node.sumCost, sc)) + } +} + +// ResumeFreeze cleans all pending requests and sets the buffer estimate to the +// reported value after resuming from a frozen state +func (node *ServerNode) ResumeFreeze(bv uint64) { + node.lock.Lock() + defer node.lock.Unlock() + + for reqID := range node.pending { + delete(node.pending, reqID) + } + now := node.clock.Now() + node.recalcBLE(now) + if bv > node.params.BufLimit { + bv = node.params.BufLimit + } + node.bufEstimate = bv + node.bufRecharge = node.bufEstimate < node.params.BufLimit + node.lastTime = now + if node.log != nil { + node.log.add(now, fmt.Sprintf("unfreeze bv=%d sumCost=%d", bv, node.sumCost)) + } +} + +// DumpLogs dumps the event log if logging is used +func (node *ServerNode) DumpLogs() { + node.lock.Lock() + defer node.lock.Unlock() + + if node.log != nil { + node.log.dump(node.clock.Now()) } - peer.lastTime = mclock.Now() } diff --git a/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/logger.go b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/logger.go new file mode 100644 index 000000000..428d7fbf2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/logger.go @@ -0,0 +1,65 @@ +// Copyright 2019 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 flowcontrol + +import ( + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common/mclock" +) + +// logger collects events in string format and discards events older than the +// "keep" parameter +type logger struct { + events map[uint64]logEvent + writePtr, delPtr uint64 + keep time.Duration +} + +// logEvent describes a single event +type logEvent struct { + time mclock.AbsTime + event string +} + +// newLogger creates a new logger +func newLogger(keep time.Duration) *logger { + return &logger{ + events: make(map[uint64]logEvent), + keep: keep, + } +} + +// add adds a new event and discards old events if possible +func (l *logger) add(now mclock.AbsTime, event string) { + keepAfter := now - mclock.AbsTime(l.keep) + for l.delPtr < l.writePtr && l.events[l.delPtr].time <= keepAfter { + delete(l.events, l.delPtr) + l.delPtr++ + } + l.events[l.writePtr] = logEvent{now, event} + l.writePtr++ +} + +// dump prints all stored events +func (l *logger) dump(now mclock.AbsTime) { + for i := l.delPtr; i < l.writePtr; i++ { + e := l.events[i] + fmt.Println(time.Duration(e.time-now), e.event) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/manager.go b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/manager.go index 28cc6f0fe..d6d0b1add 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/manager.go +++ b/vendor/github.com/ethereum/go-ethereum/les/flowcontrol/manager.go @@ -14,211 +14,449 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package flowcontrol implements a client side flow control mechanism package flowcontrol import ( + "fmt" + "math" "sync" "time" "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/common/prque" ) -const rcConst = 1000000 - -type cmNode struct { - node *ClientNode - lastUpdate mclock.AbsTime - serving, recharging bool - rcWeight uint64 - rcValue, rcDelta, startValue int64 - finishRecharge mclock.AbsTime +// cmNodeFields are ClientNode fields used by the client manager +// Note: these fields are locked by the client manager's mutex +type cmNodeFields struct { + corrBufValue int64 // buffer value adjusted with the extra recharge amount + rcLastIntValue int64 // past recharge integrator value when corrBufValue was last updated + rcFullIntValue int64 // future recharge integrator value when corrBufValue will reach maximum + queueIndex int // position in the recharge queue (-1 if not queued) } -func (node *cmNode) update(time mclock.AbsTime) { - dt := int64(time - node.lastUpdate) - node.rcValue += node.rcDelta * dt / rcConst - node.lastUpdate = time - if node.recharging && time >= node.finishRecharge { - node.recharging = false - node.rcDelta = 0 - node.rcValue = 0 - } -} +// FixedPointMultiplier is applied to the recharge integrator and the recharge curve. +// +// Note: fixed point arithmetic is required for the integrator because it is a +// constantly increasing value that can wrap around int64 limits (which behavior is +// also supported by the priority queue). A floating point value would gradually lose +// precision in this application. +// The recharge curve and all recharge values are encoded as fixed point because +// sumRecharge is frequently updated by adding or subtracting individual recharge +// values and perfect precision is required. +const FixedPointMultiplier = 1000000 -func (node *cmNode) set(serving bool, simReqCnt, sumWeight uint64) { - if node.serving && !serving { - node.recharging = true - sumWeight += node.rcWeight - } - node.serving = serving - if node.recharging && serving { - node.recharging = false - sumWeight -= node.rcWeight - } - - node.rcDelta = 0 - if serving { - node.rcDelta = int64(rcConst / simReqCnt) - } - if node.recharging { - node.rcDelta = -int64(node.node.cm.rcRecharge * node.rcWeight / sumWeight) - node.finishRecharge = node.lastUpdate + mclock.AbsTime(node.rcValue*rcConst/(-node.rcDelta)) - } -} +var ( + capacityDropFactor = 0.1 + capacityRaiseTC = 1 / (3 * float64(time.Hour)) // time constant for raising the capacity factor + capacityRaiseThresholdRatio = 1.125 // total/connected capacity ratio threshold for raising the capacity factor +) +// ClientManager controls the capacity assigned to the clients of a server. +// Since ServerParams guarantee a safe lower estimate for processable requests +// even in case of all clients being active, ClientManager calculates a +// corrigated buffer value and usually allows a higher remaining buffer value +// to be returned with each reply. type ClientManager struct { - lock sync.Mutex - nodes map[*cmNode]struct{} - simReqCnt, sumWeight, rcSumValue uint64 - maxSimReq, maxRcSum uint64 - rcRecharge uint64 - resumeQueue chan chan bool - time mclock.AbsTime + clock mclock.Clock + lock sync.Mutex + enabledCh chan struct{} + stop chan chan struct{} + + curve PieceWiseLinear + sumRecharge, totalRecharge, totalConnected uint64 + logTotalCap, totalCapacity float64 + logTotalCapRaiseLimit float64 + minLogTotalCap, maxLogTotalCap float64 + capacityRaiseThreshold uint64 + capLastUpdate mclock.AbsTime + totalCapacityCh chan uint64 + + // recharge integrator is increasing in each moment with a rate of + // (totalRecharge / sumRecharge)*FixedPointMultiplier or 0 if sumRecharge==0 + rcLastUpdate mclock.AbsTime // last time the recharge integrator was updated + rcLastIntValue int64 // last updated value of the recharge integrator + // recharge queue is a priority queue with currently recharging client nodes + // as elements. The priority value is rcFullIntValue which allows to quickly + // determine which client will first finish recharge. + rcQueue *prque.Prque } -func NewClientManager(rcTarget, maxSimReq, maxRcSum uint64) *ClientManager { +// NewClientManager returns a new client manager. +// Client manager enhances flow control performance by allowing client buffers +// to recharge quicker than the minimum guaranteed recharge rate if possible. +// The sum of all minimum recharge rates (sumRecharge) is updated each time +// a clients starts or finishes buffer recharging. Then an adjusted total +// recharge rate is calculated using a piecewise linear recharge curve: +// +// totalRecharge = curve(sumRecharge) +// (totalRecharge >= sumRecharge is enforced) +// +// Then the "bonus" buffer recharge is distributed between currently recharging +// clients proportionally to their minimum recharge rates. +// +// Note: total recharge is proportional to the average number of parallel running +// serving threads. A recharge value of 1000000 corresponds to one thread in average. +// The maximum number of allowed serving threads should always be considerably +// higher than the targeted average number. +// +// Note 2: although it is possible to specify a curve allowing the total target +// recharge starting from zero sumRecharge, it makes sense to add a linear ramp +// starting from zero in order to not let a single low-priority client use up +// the entire server capacity and thus ensure quick availability for others at +// any moment. +func NewClientManager(curve PieceWiseLinear, clock mclock.Clock) *ClientManager { cm := &ClientManager{ - nodes: make(map[*cmNode]struct{}), - resumeQueue: make(chan chan bool), - rcRecharge: rcConst * rcConst / (100*rcConst/rcTarget - rcConst), - maxSimReq: maxSimReq, - maxRcSum: maxRcSum, + clock: clock, + rcQueue: prque.New(func(a interface{}, i int) { a.(*ClientNode).queueIndex = i }), + capLastUpdate: clock.Now(), + stop: make(chan chan struct{}), } - go cm.queueProc() + if curve != nil { + cm.SetRechargeCurve(curve) + } + go func() { + // regularly recalculate and update total capacity + for { + select { + case <-time.After(time.Minute): + cm.lock.Lock() + cm.updateTotalCapacity(cm.clock.Now(), true) + cm.lock.Unlock() + case stop := <-cm.stop: + close(stop) + return + } + } + }() return cm } -func (self *ClientManager) Stop() { - self.lock.Lock() - defer self.lock.Unlock() - - // signal any waiting accept routines to return false - self.nodes = make(map[*cmNode]struct{}) - close(self.resumeQueue) +// Stop stops the client manager +func (cm *ClientManager) Stop() { + stop := make(chan struct{}) + cm.stop <- stop + <-stop } -func (self *ClientManager) addNode(cnode *ClientNode) *cmNode { - time := mclock.Now() - node := &cmNode{ - node: cnode, - lastUpdate: time, - finishRecharge: time, - rcWeight: 1, +// SetRechargeCurve updates the recharge curve +func (cm *ClientManager) SetRechargeCurve(curve PieceWiseLinear) { + cm.lock.Lock() + defer cm.lock.Unlock() + + now := cm.clock.Now() + cm.updateRecharge(now) + cm.curve = curve + if len(curve) > 0 { + cm.totalRecharge = curve[len(curve)-1].Y + } else { + cm.totalRecharge = 0 } - self.lock.Lock() - defer self.lock.Unlock() - - self.nodes[node] = struct{}{} - self.update(mclock.Now()) - return node } -func (self *ClientManager) removeNode(node *cmNode) { - self.lock.Lock() - defer self.lock.Unlock() - - time := mclock.Now() - self.stop(node, time) - delete(self.nodes, node) - self.update(time) -} - -// recalc sumWeight -func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) { - var sumWeight, rcSum uint64 - for node := range self.nodes { - rc := node.recharging - node.update(time) - if rc && !node.recharging { - rce = true - } - if node.recharging { - sumWeight += node.rcWeight - } - rcSum += uint64(node.rcValue) +// SetCapacityRaiseThreshold sets a threshold value used for raising capFactor. +// Either if the difference between total allowed and connected capacity is less +// than this threshold or if their ratio is less than capacityRaiseThresholdRatio +// then capFactor is allowed to slowly raise. +func (cm *ClientManager) SetCapacityLimits(min, max, raiseThreshold uint64) { + if min < 1 { + min = 1 } - self.sumWeight = sumWeight - self.rcSumValue = rcSum - return + cm.minLogTotalCap = math.Log(float64(min)) + if max < 1 { + max = 1 + } + cm.maxLogTotalCap = math.Log(float64(max)) + cm.logTotalCap = cm.maxLogTotalCap + cm.capacityRaiseThreshold = raiseThreshold + cm.refreshCapacity() } -func (self *ClientManager) update(time mclock.AbsTime) { - for { - firstTime := time - for node := range self.nodes { - if node.recharging && node.finishRecharge < firstTime { - firstTime = node.finishRecharge - } +// connect should be called when a client is connected, before passing it to any +// other ClientManager function +func (cm *ClientManager) connect(node *ClientNode) { + cm.lock.Lock() + defer cm.lock.Unlock() + + now := cm.clock.Now() + cm.updateRecharge(now) + node.corrBufValue = int64(node.params.BufLimit) + node.rcLastIntValue = cm.rcLastIntValue + node.queueIndex = -1 + cm.updateTotalCapacity(now, true) + cm.totalConnected += node.params.MinRecharge + cm.updateRaiseLimit() +} + +// disconnect should be called when a client is disconnected +func (cm *ClientManager) disconnect(node *ClientNode) { + cm.lock.Lock() + defer cm.lock.Unlock() + + now := cm.clock.Now() + cm.updateRecharge(cm.clock.Now()) + cm.updateTotalCapacity(now, true) + cm.totalConnected -= node.params.MinRecharge + cm.updateRaiseLimit() +} + +// accepted is called when a request with given maximum cost is accepted. +// It returns a priority indicator for the request which is used to determine placement +// in the serving queue. Older requests have higher priority by default. If the client +// is almost out of buffer, request priority is reduced. +func (cm *ClientManager) accepted(node *ClientNode, maxCost uint64, now mclock.AbsTime) (priority int64) { + cm.lock.Lock() + defer cm.lock.Unlock() + + cm.updateNodeRc(node, -int64(maxCost), &node.params, now) + rcTime := (node.params.BufLimit - uint64(node.corrBufValue)) * FixedPointMultiplier / node.params.MinRecharge + return -int64(now) - int64(rcTime) +} + +// processed updates the client buffer according to actual request cost after +// serving has been finished. +// +// Note: processed should always be called for all accepted requests +func (cm *ClientManager) processed(node *ClientNode, maxCost, realCost uint64, now mclock.AbsTime) { + if realCost > maxCost { + realCost = maxCost + } + cm.updateBuffer(node, int64(maxCost-realCost), now) +} + +// updateBuffer recalulates the corrected buffer value, adds the given value to it +// and updates the node's actual buffer value if possible +func (cm *ClientManager) updateBuffer(node *ClientNode, add int64, now mclock.AbsTime) { + cm.lock.Lock() + defer cm.lock.Unlock() + + cm.updateNodeRc(node, add, &node.params, now) + if node.corrBufValue > node.bufValue { + if node.log != nil { + node.log.add(now, fmt.Sprintf("corrected bv=%d oldBv=%d", node.corrBufValue, node.bufValue)) } - if self.updateNodes(firstTime) { - for node := range self.nodes { - if node.recharging { - node.set(node.serving, self.simReqCnt, self.sumWeight) - } - } - } else { - self.time = time + node.bufValue = node.corrBufValue + } +} + +// updateParams updates the flow control parameters of a client node +func (cm *ClientManager) updateParams(node *ClientNode, params ServerParams, now mclock.AbsTime) { + cm.lock.Lock() + defer cm.lock.Unlock() + + cm.updateRecharge(now) + cm.updateTotalCapacity(now, true) + cm.totalConnected += params.MinRecharge - node.params.MinRecharge + cm.updateRaiseLimit() + cm.updateNodeRc(node, 0, ¶ms, now) +} + +// updateRaiseLimit recalculates the limiting value until which logTotalCap +// can be raised when no client freeze events occur +func (cm *ClientManager) updateRaiseLimit() { + if cm.capacityRaiseThreshold == 0 { + cm.logTotalCapRaiseLimit = 0 + return + } + limit := float64(cm.totalConnected + cm.capacityRaiseThreshold) + limit2 := float64(cm.totalConnected) * capacityRaiseThresholdRatio + if limit2 > limit { + limit = limit2 + } + if limit < 1 { + limit = 1 + } + cm.logTotalCapRaiseLimit = math.Log(limit) +} + +// updateRecharge updates the recharge integrator and checks the recharge queue +// for nodes with recently filled buffers +func (cm *ClientManager) updateRecharge(now mclock.AbsTime) { + lastUpdate := cm.rcLastUpdate + cm.rcLastUpdate = now + // updating is done in multiple steps if node buffers are filled and sumRecharge + // is decreased before the given target time + for cm.sumRecharge > 0 { + sumRecharge := cm.sumRecharge + if sumRecharge > cm.totalRecharge { + sumRecharge = cm.totalRecharge + } + bonusRatio := float64(1) + v := cm.curve.ValueAt(sumRecharge) + s := float64(sumRecharge) + if v > s && s > 0 { + bonusRatio = v / s + } + dt := now - lastUpdate + // fetch the client that finishes first + rcqNode := cm.rcQueue.PopItem().(*ClientNode) // if sumRecharge > 0 then the queue cannot be empty + // check whether it has already finished + dtNext := mclock.AbsTime(float64(rcqNode.rcFullIntValue-cm.rcLastIntValue) / bonusRatio) + if dt < dtNext { + // not finished yet, put it back, update integrator according + // to current bonusRatio and return + cm.rcQueue.Push(rcqNode, -rcqNode.rcFullIntValue) + cm.rcLastIntValue += int64(bonusRatio * float64(dt)) return } - } -} - -func (self *ClientManager) canStartReq() bool { - return self.simReqCnt < self.maxSimReq && self.rcSumValue < self.maxRcSum -} - -func (self *ClientManager) queueProc() { - for rc := range self.resumeQueue { - for { - time.Sleep(time.Millisecond * 10) - self.lock.Lock() - self.update(mclock.Now()) - cs := self.canStartReq() - self.lock.Unlock() - if cs { - break - } + lastUpdate += dtNext + // finished recharging, update corrBufValue and sumRecharge if necessary and do next step + if rcqNode.corrBufValue < int64(rcqNode.params.BufLimit) { + rcqNode.corrBufValue = int64(rcqNode.params.BufLimit) + cm.sumRecharge -= rcqNode.params.MinRecharge } - close(rc) + cm.rcLastIntValue = rcqNode.rcFullIntValue } } -func (self *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool { - self.lock.Lock() - defer self.lock.Unlock() +// updateNodeRc updates a node's corrBufValue and adds an external correction value. +// It also adds or removes the rcQueue entry and updates ServerParams and sumRecharge if necessary. +func (cm *ClientManager) updateNodeRc(node *ClientNode, bvc int64, params *ServerParams, now mclock.AbsTime) { + cm.updateRecharge(now) + wasFull := true + if node.corrBufValue != int64(node.params.BufLimit) { + wasFull = false + node.corrBufValue += (cm.rcLastIntValue - node.rcLastIntValue) * int64(node.params.MinRecharge) / FixedPointMultiplier + if node.corrBufValue > int64(node.params.BufLimit) { + node.corrBufValue = int64(node.params.BufLimit) + } + node.rcLastIntValue = cm.rcLastIntValue + } + node.corrBufValue += bvc + diff := int64(params.BufLimit - node.params.BufLimit) + if diff > 0 { + node.corrBufValue += diff + } + isFull := false + if node.corrBufValue >= int64(params.BufLimit) { + node.corrBufValue = int64(params.BufLimit) + isFull = true + } + if !wasFull { + cm.sumRecharge -= node.params.MinRecharge + } + if params != &node.params { + node.params = *params + } + if !isFull { + cm.sumRecharge += node.params.MinRecharge + if node.queueIndex != -1 { + cm.rcQueue.Remove(node.queueIndex) + } + node.rcLastIntValue = cm.rcLastIntValue + node.rcFullIntValue = cm.rcLastIntValue + (int64(node.params.BufLimit)-node.corrBufValue)*FixedPointMultiplier/int64(node.params.MinRecharge) + cm.rcQueue.Push(node, -node.rcFullIntValue) + } +} - self.update(time) - if !self.canStartReq() { - resume := make(chan bool) - self.lock.Unlock() - self.resumeQueue <- resume - <-resume - self.lock.Lock() - if _, ok := self.nodes[node]; !ok { - return false // reject if node has been removed or manager has been stopped +// reduceTotalCapacity reduces the total capacity allowance in case of a client freeze event +func (cm *ClientManager) reduceTotalCapacity(frozenCap uint64) { + cm.lock.Lock() + defer cm.lock.Unlock() + + ratio := float64(1) + if frozenCap < cm.totalConnected { + ratio = float64(frozenCap) / float64(cm.totalConnected) + } + now := cm.clock.Now() + cm.updateTotalCapacity(now, false) + cm.logTotalCap -= capacityDropFactor * ratio + if cm.logTotalCap < cm.minLogTotalCap { + cm.logTotalCap = cm.minLogTotalCap + } + cm.updateTotalCapacity(now, true) +} + +// updateTotalCapacity updates the total capacity factor. The capacity factor allows +// the total capacity of the system to go over the allowed total recharge value +// if clients go to frozen state sufficiently rarely. +// The capacity factor is dropped instantly by a small amount if a clients is frozen. +// It is raised slowly (with a large time constant) if the total connected capacity +// is close to the total allowed amount and no clients are frozen. +func (cm *ClientManager) updateTotalCapacity(now mclock.AbsTime, refresh bool) { + dt := now - cm.capLastUpdate + cm.capLastUpdate = now + + if cm.logTotalCap < cm.logTotalCapRaiseLimit { + cm.logTotalCap += capacityRaiseTC * float64(dt) + if cm.logTotalCap > cm.logTotalCapRaiseLimit { + cm.logTotalCap = cm.logTotalCapRaiseLimit } } - self.simReqCnt++ - node.set(true, self.simReqCnt, self.sumWeight) - node.startValue = node.rcValue - self.update(self.time) + if cm.logTotalCap > cm.maxLogTotalCap { + cm.logTotalCap = cm.maxLogTotalCap + } + if refresh { + cm.refreshCapacity() + } +} + +// refreshCapacity recalculates the total capacity value and sends an update to the subscription +// channel if the relative change of the value since the last update is more than 0.1 percent +func (cm *ClientManager) refreshCapacity() { + totalCapacity := math.Exp(cm.logTotalCap) + if totalCapacity >= cm.totalCapacity*0.999 && totalCapacity <= cm.totalCapacity*1.001 { + return + } + cm.totalCapacity = totalCapacity + if cm.totalCapacityCh != nil { + select { + case cm.totalCapacityCh <- uint64(cm.totalCapacity): + default: + } + } +} + +// SubscribeTotalCapacity returns all future updates to the total capacity value +// through a channel and also returns the current value +func (cm *ClientManager) SubscribeTotalCapacity(ch chan uint64) uint64 { + cm.lock.Lock() + defer cm.lock.Unlock() + + cm.totalCapacityCh = ch + return uint64(cm.totalCapacity) +} + +// PieceWiseLinear is used to describe recharge curves +type PieceWiseLinear []struct{ X, Y uint64 } + +// ValueAt returns the curve's value at a given point +func (pwl PieceWiseLinear) ValueAt(x uint64) float64 { + l := 0 + h := len(pwl) + if h == 0 { + return 0 + } + for h != l { + m := (l + h) / 2 + if x > pwl[m].X { + l = m + 1 + } else { + h = m + } + } + if l == 0 { + return float64(pwl[0].Y) + } + l-- + if h == len(pwl) { + return float64(pwl[l].Y) + } + dx := pwl[h].X - pwl[l].X + if dx < 1 { + return float64(pwl[l].Y) + } + return float64(pwl[l].Y) + float64(pwl[h].Y-pwl[l].Y)*float64(x-pwl[l].X)/float64(dx) +} + +// Valid returns true if the X coordinates of the curve points are non-strictly monotonic +func (pwl PieceWiseLinear) Valid() bool { + var lastX uint64 + for _, i := range pwl { + if i.X < lastX { + return false + } + lastX = i.X + } return true } - -func (self *ClientManager) stop(node *cmNode, time mclock.AbsTime) { - if node.serving { - self.update(time) - self.simReqCnt-- - node.set(false, self.simReqCnt, self.sumWeight) - self.update(time) - } -} - -func (self *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) { - self.lock.Lock() - defer self.lock.Unlock() - - self.stop(node, time) - return uint64(node.rcValue), uint64(node.rcValue - node.startValue) -} diff --git a/vendor/github.com/ethereum/go-ethereum/les/freeclient.go b/vendor/github.com/ethereum/go-ethereum/les/freeclient.go deleted file mode 100644 index 5ee607be8..000000000 --- a/vendor/github.com/ethereum/go-ethereum/les/freeclient.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Package les implements the Light Ethereum Subprotocol. -package les - -import ( - "io" - "math" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// freeClientPool implements a client database that limits the connection time -// of each client and manages accepting/rejecting incoming connections and even -// kicking out some connected clients. The pool calculates recent usage time -// for each known client (a value that increases linearly when the client is -// connected and decreases exponentially when not connected). Clients with lower -// recent usage are preferred, unknown nodes have the highest priority. Already -// connected nodes receive a small bias in their favor in order to avoid accepting -// and instantly kicking out clients. -// -// Note: the pool can use any string for client identification. Using signature -// keys for that purpose would not make sense when being known has a negative -// value for the client. Currently the LES protocol manager uses IP addresses -// (without port address) to identify clients. -type freeClientPool struct { - db ethdb.Database - lock sync.Mutex - clock mclock.Clock - closed bool - - connectedLimit, totalLimit int - - addressMap map[string]*freeClientPoolEntry - connPool, disconnPool *prque.Prque - startupTime mclock.AbsTime - logOffsetAtStartup int64 -} - -const ( - recentUsageExpTC = time.Hour // time constant of the exponential weighting window for "recent" server usage - fixedPointMultiplier = 0x1000000 // constant to convert logarithms to fixed point format - connectedBias = time.Minute // this bias is applied in favor of already connected clients in order to avoid kicking them out very soon -) - -// newFreeClientPool creates a new free client pool -func newFreeClientPool(db ethdb.Database, connectedLimit, totalLimit int, clock mclock.Clock) *freeClientPool { - pool := &freeClientPool{ - db: db, - clock: clock, - addressMap: make(map[string]*freeClientPoolEntry), - connPool: prque.New(poolSetIndex), - disconnPool: prque.New(poolSetIndex), - connectedLimit: connectedLimit, - totalLimit: totalLimit, - } - pool.loadFromDb() - return pool -} - -func (f *freeClientPool) stop() { - f.lock.Lock() - f.closed = true - f.saveToDb() - f.lock.Unlock() -} - -// connect should be called after a successful handshake. If the connection was -// rejected, there is no need to call disconnect. -// -// Note: the disconnectFn callback should not block. -func (f *freeClientPool) connect(address string, disconnectFn func()) bool { - f.lock.Lock() - defer f.lock.Unlock() - - if f.closed { - return false - } - e := f.addressMap[address] - now := f.clock.Now() - var recentUsage int64 - if e == nil { - e = &freeClientPoolEntry{address: address, index: -1} - f.addressMap[address] = e - } else { - if e.connected { - log.Debug("Client already connected", "address", address) - return false - } - recentUsage = int64(math.Exp(float64(e.logUsage-f.logOffset(now)) / fixedPointMultiplier)) - } - e.linUsage = recentUsage - int64(now) - // check whether (linUsage+connectedBias) is smaller than the highest entry in the connected pool - if f.connPool.Size() == f.connectedLimit { - i := f.connPool.PopItem().(*freeClientPoolEntry) - if e.linUsage+int64(connectedBias)-i.linUsage < 0 { - // kick it out and accept the new client - f.connPool.Remove(i.index) - f.calcLogUsage(i, now) - i.connected = false - f.disconnPool.Push(i, -i.logUsage) - log.Debug("Client kicked out", "address", i.address) - i.disconnectFn() - } else { - // keep the old client and reject the new one - f.connPool.Push(i, i.linUsage) - log.Debug("Client rejected", "address", address) - return false - } - } - f.disconnPool.Remove(e.index) - e.connected = true - e.disconnectFn = disconnectFn - f.connPool.Push(e, e.linUsage) - if f.connPool.Size()+f.disconnPool.Size() > f.totalLimit { - f.disconnPool.Pop() - } - log.Debug("Client accepted", "address", address) - return true -} - -// disconnect should be called when a connection is terminated. If the disconnection -// was initiated by the pool itself using disconnectFn then calling disconnect is -// not necessary but permitted. -func (f *freeClientPool) disconnect(address string) { - f.lock.Lock() - defer f.lock.Unlock() - - if f.closed { - return - } - e := f.addressMap[address] - now := f.clock.Now() - if !e.connected { - log.Debug("Client already disconnected", "address", address) - return - } - - f.connPool.Remove(e.index) - f.calcLogUsage(e, now) - e.connected = false - f.disconnPool.Push(e, -e.logUsage) - log.Debug("Client disconnected", "address", address) -} - -// logOffset calculates the time-dependent offset for the logarithmic -// representation of recent usage -func (f *freeClientPool) logOffset(now mclock.AbsTime) int64 { - // Note: fixedPointMultiplier acts as a multiplier here; the reason for dividing the divisor - // is to avoid int64 overflow. We assume that int64(recentUsageExpTC) >> fixedPointMultiplier. - logDecay := int64((time.Duration(now - f.startupTime)) / (recentUsageExpTC / fixedPointMultiplier)) - return f.logOffsetAtStartup + logDecay -} - -// calcLogUsage converts recent usage from linear to logarithmic representation -// when disconnecting a peer or closing the client pool -func (f *freeClientPool) calcLogUsage(e *freeClientPoolEntry, now mclock.AbsTime) { - dt := e.linUsage + int64(now) - if dt < 1 { - dt = 1 - } - e.logUsage = int64(math.Log(float64(dt))*fixedPointMultiplier) + f.logOffset(now) -} - -// freeClientPoolStorage is the RLP representation of the pool's database storage -type freeClientPoolStorage struct { - LogOffset uint64 - List []*freeClientPoolEntry -} - -// loadFromDb restores pool status from the database storage -// (automatically called at initialization) -func (f *freeClientPool) loadFromDb() { - enc, err := f.db.Get([]byte("freeClientPool")) - if err != nil { - return - } - var storage freeClientPoolStorage - err = rlp.DecodeBytes(enc, &storage) - if err != nil { - log.Error("Failed to decode client list", "err", err) - return - } - f.logOffsetAtStartup = int64(storage.LogOffset) - f.startupTime = f.clock.Now() - for _, e := range storage.List { - log.Debug("Loaded free client record", "address", e.address, "logUsage", e.logUsage) - f.addressMap[e.address] = e - f.disconnPool.Push(e, -e.logUsage) - } -} - -// saveToDb saves pool status to the database storage -// (automatically called during shutdown) -func (f *freeClientPool) saveToDb() { - now := f.clock.Now() - storage := freeClientPoolStorage{ - LogOffset: uint64(f.logOffset(now)), - List: make([]*freeClientPoolEntry, len(f.addressMap)), - } - i := 0 - for _, e := range f.addressMap { - if e.connected { - f.calcLogUsage(e, now) - } - storage.List[i] = e - i++ - } - enc, err := rlp.EncodeToBytes(storage) - if err != nil { - log.Error("Failed to encode client list", "err", err) - } else { - f.db.Put([]byte("freeClientPool"), enc) - } -} - -// freeClientPoolEntry represents a client address known by the pool. -// When connected, recent usage is calculated as linUsage + int64(clock.Now()) -// When disconnected, it is calculated as exp(logUsage - logOffset) where logOffset -// also grows linearly with time while the server is running. -// Conversion between linear and logarithmic representation happens when connecting -// or disconnecting the node. -// -// Note: linUsage and logUsage are values used with constantly growing offsets so -// even though they are close to each other at any time they may wrap around int64 -// limits over time. Comparison should be performed accordingly. -type freeClientPoolEntry struct { - address string - connected bool - disconnectFn func() - linUsage, logUsage int64 - index int -} - -func (e *freeClientPoolEntry) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, []interface{}{e.address, uint64(e.logUsage)}) -} - -func (e *freeClientPoolEntry) DecodeRLP(s *rlp.Stream) error { - var entry struct { - Address string - LogUsage uint64 - } - if err := s.Decode(&entry); err != nil { - return err - } - e.address = entry.Address - e.logUsage = int64(entry.LogUsage) - e.connected = false - e.index = -1 - return nil -} - -// poolSetIndex callback is used by both priority queues to set/update the index of -// the element in the queue. Index is needed to remove elements other than the top one. -func poolSetIndex(a interface{}, i int) { - a.(*freeClientPoolEntry).index = i -} diff --git a/vendor/github.com/ethereum/go-ethereum/les/handler.go b/vendor/github.com/ethereum/go-ethereum/les/handler.go deleted file mode 100644 index 953f7a2c1..000000000 --- a/vendor/github.com/ethereum/go-ethereum/les/handler.go +++ /dev/null @@ -1,1298 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Package les implements the Light Ethereum Subprotocol. -package les - -import ( - "encoding/binary" - "encoding/json" - "fmt" - "math/big" - "net" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/light" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/discv5" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -const ( - softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. - estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header - - ethVersion = 63 // equivalent eth version for the downloader - - MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request - MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request - MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request - MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request - MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request - MaxHelperTrieProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request - MaxTxSend = 64 // Amount of transactions to be send per request - MaxTxStatus = 256 // Amount of transactions to queried per request - - disableClientRemovePeer = false -) - -func errResp(code errCode, format string, v ...interface{}) error { - return fmt.Errorf("%v - %v", code, fmt.Sprintf(format, v...)) -} - -type BlockChain interface { - Config() *params.ChainConfig - HasHeader(hash common.Hash, number uint64) bool - GetHeader(hash common.Hash, number uint64) *types.Header - GetHeaderByHash(hash common.Hash) *types.Header - CurrentHeader() *types.Header - GetTd(hash common.Hash, number uint64) *big.Int - State() (*state.StateDB, error) - InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) - Rollback(chain []common.Hash) - GetHeaderByNumber(number uint64) *types.Header - GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) - Genesis() *types.Block - SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription -} - -type txPool interface { - AddRemotes(txs []*types.Transaction) []error - Status(hashes []common.Hash) []core.TxStatus -} - -type ProtocolManager struct { - lightSync bool - txpool txPool - txrelay *LesTxRelay - networkId uint64 - chainConfig *params.ChainConfig - iConfig *light.IndexerConfig - blockchain BlockChain - chainDb ethdb.Database - odr *LesOdr - server *LesServer - serverPool *serverPool - clientPool *freeClientPool - lesTopic discv5.Topic - reqDist *requestDistributor - retriever *retrieveManager - - downloader *downloader.Downloader - fetcher *lightFetcher - peers *peerSet - maxPeers int - - eventMux *event.TypeMux - - // channels for fetcher, syncer, txsyncLoop - newPeerCh chan *peer - quitSync chan struct{} - noMorePeers chan struct{} - - // wait group is used for graceful shutdowns during downloading - // and processing - wg *sync.WaitGroup - ulc *ulc -} - -// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable -// with the ethereum network. -func NewProtocolManager( - chainConfig *params.ChainConfig, - indexerConfig *light.IndexerConfig, - lightSync bool, - networkId uint64, - mux *event.TypeMux, - engine consensus.Engine, - peers *peerSet, - blockchain BlockChain, - txpool txPool, - chainDb ethdb.Database, - odr *LesOdr, - txrelay *LesTxRelay, - serverPool *serverPool, - quitSync chan struct{}, - wg *sync.WaitGroup, - ulcConfig *eth.ULCConfig) (*ProtocolManager, error) { - // Create the protocol manager with the base fields - manager := &ProtocolManager{ - lightSync: lightSync, - eventMux: mux, - blockchain: blockchain, - chainConfig: chainConfig, - iConfig: indexerConfig, - chainDb: chainDb, - odr: odr, - networkId: networkId, - txpool: txpool, - txrelay: txrelay, - serverPool: serverPool, - peers: peers, - newPeerCh: make(chan *peer), - quitSync: quitSync, - wg: wg, - noMorePeers: make(chan struct{}), - } - if odr != nil { - manager.retriever = odr.retriever - manager.reqDist = odr.retriever.dist - } - - if ulcConfig != nil { - manager.ulc = newULC(ulcConfig) - } - - removePeer := manager.removePeer - if disableClientRemovePeer { - removePeer = func(id string) {} - } - if lightSync { - var checkpoint uint64 - if cht, ok := params.TrustedCheckpoints[blockchain.Genesis().Hash()]; ok { - checkpoint = (cht.SectionIndex+1)*params.CHTFrequencyClient - 1 - } - manager.downloader = downloader.New(downloader.LightSync, checkpoint, chainDb, manager.eventMux, nil, blockchain, removePeer) - manager.peers.notify((*downloaderPeerNotify)(manager)) - manager.fetcher = newLightFetcher(manager) - } - - return manager, nil -} - -// removePeer initiates disconnection from a peer by removing it from the peer set -func (pm *ProtocolManager) removePeer(id string) { - pm.peers.Unregister(id) -} - -func (pm *ProtocolManager) Start(maxPeers int) { - pm.maxPeers = maxPeers - - if pm.lightSync { - go pm.syncer() - } else { - pm.clientPool = newFreeClientPool(pm.chainDb, maxPeers, 10000, mclock.System{}) - go func() { - for range pm.newPeerCh { - } - }() - } -} - -func (pm *ProtocolManager) Stop() { - // Showing a log message. During download / process this could actually - // take between 5 to 10 seconds and therefor feedback is required. - log.Info("Stopping light Ethereum protocol") - - // Quit the sync loop. - // After this send has completed, no new peers will be accepted. - pm.noMorePeers <- struct{}{} - - close(pm.quitSync) // quits syncer, fetcher - if pm.clientPool != nil { - pm.clientPool.stop() - } - - // Stop downloader and make sure that all the running downloads are complete. - pm.downloader.Terminate() - - // Disconnect existing sessions. - // This also closes the gate for any new registrations on the peer set. - // sessions which are already established but not added to pm.peers yet - // will exit when they try to register. - pm.peers.Close() - - // Wait for any process action - pm.wg.Wait() - - log.Info("Light Ethereum protocol stopped") -} - -// runPeer is the p2p protocol run function for the given version. -func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { - var entry *poolEntry - peer := pm.newPeer(int(version), pm.networkId, p, rw) - if pm.serverPool != nil { - entry = pm.serverPool.connect(peer, peer.Node()) - } - peer.poolEntry = entry - select { - case pm.newPeerCh <- peer: - pm.wg.Add(1) - defer pm.wg.Done() - err := pm.handle(peer) - if entry != nil { - pm.serverPool.disconnect(entry) - } - return err - case <-pm.quitSync: - if entry != nil { - pm.serverPool.disconnect(entry) - } - return p2p.DiscQuitting - } -} - -func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { - var isTrusted bool - if pm.isULCEnabled() { - isTrusted = pm.ulc.isTrusted(p.ID()) - } - return newPeer(pv, nv, isTrusted, p, newMeteredMsgWriter(rw)) -} - -// handle is the callback invoked to manage the life cycle of a les peer. When -// this function terminates, the peer is disconnected. -func (pm *ProtocolManager) handle(p *peer) error { - // Ignore maxPeers if this is a trusted peer - // In server mode we try to check into the client pool after handshake - if pm.lightSync && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { - return p2p.DiscTooManyPeers - } - - p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) - - // Execute the LES handshake - var ( - genesis = pm.blockchain.Genesis() - head = pm.blockchain.CurrentHeader() - hash = head.Hash() - number = head.Number.Uint64() - td = pm.blockchain.GetTd(hash, number) - ) - if err := p.Handshake(td, hash, number, genesis.Hash(), pm.server); err != nil { - p.Log().Debug("Light Ethereum handshake failed", "err", err) - return err - } - - if !pm.lightSync && !p.Peer.Info().Network.Trusted { - addr, ok := p.RemoteAddr().(*net.TCPAddr) - // test peer address is not a tcp address, don't use client pool if can not typecast - if ok { - id := addr.IP.String() - if !pm.clientPool.connect(id, func() { go pm.removePeer(p.id) }) { - return p2p.DiscTooManyPeers - } - defer pm.clientPool.disconnect(id) - } - } - - if rw, ok := p.rw.(*meteredMsgReadWriter); ok { - rw.Init(p.version) - } - - // Register the peer locally - if err := pm.peers.Register(p); err != nil { - p.Log().Error("Light Ethereum peer registration failed", "err", err) - return err - } - defer func() { - if pm.server != nil && pm.server.fcManager != nil && p.fcClient != nil { - p.fcClient.Remove(pm.server.fcManager) - } - pm.removePeer(p.id) - }() - - // Register the peer in the downloader. If the downloader considers it banned, we disconnect - if pm.lightSync { - p.lock.Lock() - head := p.headInfo - p.lock.Unlock() - if pm.fetcher != nil { - pm.fetcher.announce(p, head) - } - - if p.poolEntry != nil { - pm.serverPool.registered(p.poolEntry) - } - } - - stop := make(chan struct{}) - defer close(stop) - go func() { - // new block announce loop - for { - select { - case announce := <-p.announceChn: - p.SendAnnounce(announce) - case <-stop: - return - } - } - }() - - // main loop. handle incoming messages. - for { - if err := pm.handleMsg(p); err != nil { - p.Log().Debug("Light Ethereum message handling failed", "err", err) - return err - } - } -} - -var ( - reqList = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsV1Msg, SendTxMsg, SendTxV2Msg, GetTxStatusMsg, GetHeaderProofsMsg, GetProofsV2Msg, GetHelperTrieProofsMsg} - reqListV1 = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, GetProofsV1Msg, SendTxMsg, GetHeaderProofsMsg} - reqListV2 = []uint64{GetBlockHeadersMsg, GetBlockBodiesMsg, GetCodeMsg, GetReceiptsMsg, SendTxV2Msg, GetTxStatusMsg, GetProofsV2Msg, GetHelperTrieProofsMsg} -) - -// handleMsg is invoked whenever an inbound message is received from a remote -// peer. The remote connection is torn down upon returning any error. -func (pm *ProtocolManager) handleMsg(p *peer) error { - // Read the next message from the remote peer, and ensure it's fully consumed - msg, err := p.rw.ReadMsg() - if err != nil { - return err - } - p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) - - costs := p.fcCosts[msg.Code] - reject := func(reqCnt, maxCnt uint64) bool { - if p.fcClient == nil || reqCnt > maxCnt { - return true - } - bufValue, _ := p.fcClient.AcceptRequest() - cost := costs.baseCost + reqCnt*costs.reqCost - if cost > pm.server.defParams.BufLimit { - cost = pm.server.defParams.BufLimit - } - if cost > bufValue { - recharge := time.Duration((cost - bufValue) * 1000000 / pm.server.defParams.MinRecharge) - p.Log().Error("Request came too early", "recharge", common.PrettyDuration(recharge)) - return true - } - return false - } - - if msg.Size > ProtocolMaxMsgSize { - return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) - } - defer msg.Discard() - - var deliverMsg *Msg - - // Handle the message depending on its contents - switch msg.Code { - case StatusMsg: - p.Log().Trace("Received status message") - // Status messages should never arrive after the handshake - return errResp(ErrExtraStatusMsg, "uncontrolled status message") - - // Block header query, collect the requested headers and reply - case AnnounceMsg: - p.Log().Trace("Received announce message") - if p.announceType == announceTypeNone { - return errResp(ErrUnexpectedResponse, "") - } - var req announceData - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "%v: %v", msg, err) - } - - if p.announceType == announceTypeSigned { - if err := req.checkSignature(p.ID()); err != nil { - p.Log().Trace("Invalid announcement signature", "err", err) - return err - } - p.Log().Trace("Valid announcement signature") - } - - p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth) - if pm.fetcher != nil { - pm.fetcher.announce(p, &req) - } - - case GetBlockHeadersMsg: - p.Log().Trace("Received block header request") - // Decode the complex header query - var req struct { - ReqID uint64 - Query getBlockHeadersData - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "%v: %v", msg, err) - } - - query := req.Query - if reject(query.Amount, MaxHeaderFetch) { - return errResp(ErrRequestRejected, "") - } - - hashMode := query.Origin.Hash != (common.Hash{}) - first := true - maxNonCanonical := uint64(100) - - // Gather headers until the fetch or network limits is reached - var ( - bytes common.StorageSize - headers []*types.Header - unknown bool - ) - for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { - // Retrieve the next header satisfying the query - var origin *types.Header - if hashMode { - if first { - first = false - origin = pm.blockchain.GetHeaderByHash(query.Origin.Hash) - if origin != nil { - query.Origin.Number = origin.Number.Uint64() - } - } else { - origin = pm.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) - } - } else { - origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) - } - if origin == nil { - break - } - headers = append(headers, origin) - bytes += estHeaderRlpSize - - // Advance to the next header of the query - switch { - case hashMode && query.Reverse: - // Hash based traversal towards the genesis block - ancestor := query.Skip + 1 - if ancestor == 0 { - unknown = true - } else { - query.Origin.Hash, query.Origin.Number = pm.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) - unknown = (query.Origin.Hash == common.Hash{}) - } - case hashMode && !query.Reverse: - // Hash based traversal towards the leaf block - var ( - current = origin.Number.Uint64() - next = current + query.Skip + 1 - ) - if next <= current { - infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") - p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) - unknown = true - } else { - if header := pm.blockchain.GetHeaderByNumber(next); header != nil { - nextHash := header.Hash() - expOldHash, _ := pm.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) - if expOldHash == query.Origin.Hash { - query.Origin.Hash, query.Origin.Number = nextHash, next - } else { - unknown = true - } - } else { - unknown = true - } - } - case query.Reverse: - // Number based traversal towards the genesis block - if query.Origin.Number >= query.Skip+1 { - query.Origin.Number -= query.Skip + 1 - } else { - unknown = true - } - - case !query.Reverse: - // Number based traversal towards the leaf block - query.Origin.Number += query.Skip + 1 - } - } - - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + query.Amount*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, query.Amount, rcost) - return p.SendBlockHeaders(req.ReqID, bv, headers) - - case BlockHeadersMsg: - if pm.downloader == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received block header response message") - // A batch of headers arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Headers []*types.Header - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - if pm.fetcher != nil && pm.fetcher.requestedID(resp.ReqID) { - pm.fetcher.deliverHeaders(p, resp.ReqID, resp.Headers) - } else { - err := pm.downloader.DeliverHeaders(p.id, resp.Headers) - if err != nil { - log.Debug(fmt.Sprint(err)) - } - } - - case GetBlockBodiesMsg: - p.Log().Trace("Received block bodies request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather blocks until the fetch or network limits is reached - var ( - bytes int - bodies []rlp.RawValue - ) - reqCnt := len(req.Hashes) - if reject(uint64(reqCnt), MaxBodyFetch) { - return errResp(ErrRequestRejected, "") - } - for _, hash := range req.Hashes { - if bytes >= softResponseLimit { - break - } - // Retrieve the requested block body, stopping if enough was found - if number := rawdb.ReadHeaderNumber(pm.chainDb, hash); number != nil { - if data := rawdb.ReadBodyRLP(pm.chainDb, hash, *number); len(data) != 0 { - bodies = append(bodies, data) - bytes += len(data) - } - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendBlockBodiesRLP(req.ReqID, bv, bodies) - - case BlockBodiesMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received block bodies response") - // A batch of block bodies arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data []*types.Body - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgBlockBodies, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetCodeMsg: - p.Log().Trace("Received code request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []CodeReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - data [][]byte - ) - reqCnt := len(req.Reqs) - if reject(uint64(reqCnt), MaxCodeFetch) { - return errResp(ErrRequestRejected, "") - } - for _, req := range req.Reqs { - // Retrieve the requested state entry, stopping if enough was found - if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { - if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, err := pm.blockchain.State() - if err != nil { - continue - } - account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey)) - if err != nil { - continue - } - code, _ := statedb.Database().TrieDB().Node(common.BytesToHash(account.CodeHash)) - - data = append(data, code) - if bytes += len(code); bytes >= softResponseLimit { - break - } - } - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendCode(req.ReqID, bv, data) - - case CodeMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received code response") - // A batch of node state data arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data [][]byte - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgCode, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetReceiptsMsg: - p.Log().Trace("Received receipts request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - receipts []rlp.RawValue - ) - reqCnt := len(req.Hashes) - if reject(uint64(reqCnt), MaxReceiptFetch) { - return errResp(ErrRequestRejected, "") - } - for _, hash := range req.Hashes { - if bytes >= softResponseLimit { - break - } - // Retrieve the requested block's receipts, skipping if unknown to us - var results types.Receipts - if number := rawdb.ReadHeaderNumber(pm.chainDb, hash); number != nil { - results = rawdb.ReadReceipts(pm.chainDb, hash, *number) - } - if results == nil { - if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { - continue - } - } - // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(results); err != nil { - log.Error("Failed to encode receipt", "err", err) - } else { - receipts = append(receipts, encoded) - bytes += len(encoded) - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendReceiptsRLP(req.ReqID, bv, receipts) - - case ReceiptsMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received receipts response") - // A batch of receipts arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Receipts []types.Receipts - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgReceipts, - ReqID: resp.ReqID, - Obj: resp.Receipts, - } - - case GetProofsV1Msg: - p.Log().Trace("Received proofs request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []ProofReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - proofs proofsData - ) - reqCnt := len(req.Reqs) - if reject(uint64(reqCnt), MaxProofsFetch) { - return errResp(ErrRequestRejected, "") - } - for _, req := range req.Reqs { - // Retrieve the requested state entry, stopping if enough was found - if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { - if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, err := pm.blockchain.State() - if err != nil { - continue - } - var trie state.Trie - if len(req.AccKey) > 0 { - account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey)) - if err != nil { - continue - } - trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root) - } else { - trie, _ = statedb.Database().OpenTrie(header.Root) - } - if trie != nil { - var proof light.NodeList - trie.Prove(req.Key, 0, &proof) - - proofs = append(proofs, proof) - if bytes += proof.DataSize(); bytes >= softResponseLimit { - break - } - } - } - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendProofs(req.ReqID, bv, proofs) - - case GetProofsV2Msg: - p.Log().Trace("Received les/2 proofs request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []ProofReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - lastBHash common.Hash - statedb *state.StateDB - root common.Hash - ) - reqCnt := len(req.Reqs) - if reject(uint64(reqCnt), MaxProofsFetch) { - return errResp(ErrRequestRejected, "") - } - - nodes := light.NewNodeSet() - - for _, req := range req.Reqs { - // Look up the state belonging to the request - if statedb == nil || req.BHash != lastBHash { - statedb, root, lastBHash = nil, common.Hash{}, req.BHash - - if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { - if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, _ = pm.blockchain.State() - root = header.Root - } - } - } - if statedb == nil { - continue - } - // Pull the account or storage trie of the request - var trie state.Trie - if len(req.AccKey) > 0 { - account, err := pm.getAccount(statedb, root, common.BytesToHash(req.AccKey)) - if err != nil { - continue - } - trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root) - } else { - trie, _ = statedb.Database().OpenTrie(root) - } - if trie == nil { - continue - } - // Prove the user's request from the account or stroage trie - trie.Prove(req.Key, req.FromLevel, nodes) - if nodes.DataSize() >= softResponseLimit { - break - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendProofsV2(req.ReqID, bv, nodes.NodeList()) - - case ProofsV1Msg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received proofs response") - // A batch of merkle proofs arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data []light.NodeList - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgProofsV1, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case ProofsV2Msg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received les/2 proofs response") - // A batch of merkle proofs arrived to one of our previous requests - var resp struct { - ReqID, BV uint64 - Data light.NodeList - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgProofsV2, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case GetHeaderProofsMsg: - p.Log().Trace("Received headers proof request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []ChtReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - bytes int - proofs []ChtResp - ) - reqCnt := len(req.Reqs) - if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) { - return errResp(ErrRequestRejected, "") - } - trieDb := trie.NewDatabase(ethdb.NewTable(pm.chainDb, light.ChtTablePrefix)) - for _, req := range req.Reqs { - if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil { - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, req.ChtNum*pm.iConfig.ChtSize-1) - if root := light.GetChtRoot(pm.chainDb, req.ChtNum-1, sectionHead); root != (common.Hash{}) { - trie, err := trie.New(root, trieDb) - if err != nil { - continue - } - var encNumber [8]byte - binary.BigEndian.PutUint64(encNumber[:], req.BlockNum) - - var proof light.NodeList - trie.Prove(encNumber[:], 0, &proof) - - proofs = append(proofs, ChtResp{Header: header, Proof: proof}) - if bytes += proof.DataSize() + estHeaderRlpSize; bytes >= softResponseLimit { - break - } - } - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendHeaderProofs(req.ReqID, bv, proofs) - - case GetHelperTrieProofsMsg: - p.Log().Trace("Received helper trie proof request") - // Decode the retrieval message - var req struct { - ReqID uint64 - Reqs []HelperTrieReq - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - // Gather state data until the fetch or network limits is reached - var ( - auxBytes int - auxData [][]byte - ) - reqCnt := len(req.Reqs) - if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) { - return errResp(ErrRequestRejected, "") - } - - var ( - lastIdx uint64 - lastType uint - root common.Hash - auxTrie *trie.Trie - ) - nodes := light.NewNodeSet() - for _, req := range req.Reqs { - if auxTrie == nil || req.Type != lastType || req.TrieIdx != lastIdx { - auxTrie, lastType, lastIdx = nil, req.Type, req.TrieIdx - - var prefix string - if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) { - auxTrie, _ = trie.New(root, trie.NewDatabase(ethdb.NewTable(pm.chainDb, prefix))) - } - } - if req.AuxReq == auxRoot { - var data []byte - if root != (common.Hash{}) { - data = root[:] - } - auxData = append(auxData, data) - auxBytes += len(data) - } else { - if auxTrie != nil { - auxTrie.Prove(req.Key, req.FromLevel, nodes) - } - if req.AuxReq != 0 { - data := pm.getHelperTrieAuxData(req) - auxData = append(auxData, data) - auxBytes += len(data) - } - } - if nodes.DataSize()+auxBytes >= softResponseLimit { - break - } - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}) - - case HeaderProofsMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received headers proof response") - var resp struct { - ReqID, BV uint64 - Data []ChtResp - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgHeaderProofs, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case HelperTrieProofsMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received helper trie proof response") - var resp struct { - ReqID, BV uint64 - Data HelperTrieResps - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - - p.fcServer.GotReply(resp.ReqID, resp.BV) - deliverMsg = &Msg{ - MsgType: MsgHelperTrieProofs, - ReqID: resp.ReqID, - Obj: resp.Data, - } - - case SendTxMsg: - if pm.txpool == nil { - return errResp(ErrRequestRejected, "") - } - // Transactions arrived, parse all of them and deliver to the pool - var txs []*types.Transaction - if err := msg.Decode(&txs); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - reqCnt := len(txs) - if reject(uint64(reqCnt), MaxTxSend) { - return errResp(ErrRequestRejected, "") - } - pm.txpool.AddRemotes(txs) - - _, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - - case SendTxV2Msg: - if pm.txpool == nil { - return errResp(ErrRequestRejected, "") - } - // Transactions arrived, parse all of them and deliver to the pool - var req struct { - ReqID uint64 - Txs []*types.Transaction - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - reqCnt := len(req.Txs) - if reject(uint64(reqCnt), MaxTxSend) { - return errResp(ErrRequestRejected, "") - } - - hashes := make([]common.Hash, len(req.Txs)) - for i, tx := range req.Txs { - hashes[i] = tx.Hash() - } - stats := pm.txStatus(hashes) - for i, stat := range stats { - if stat.Status == core.TxStatusUnknown { - if errs := pm.txpool.AddRemotes([]*types.Transaction{req.Txs[i]}); errs[0] != nil { - stats[i].Error = errs[0].Error() - continue - } - stats[i] = pm.txStatus([]common.Hash{hashes[i]})[0] - } - } - - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - - return p.SendTxStatus(req.ReqID, bv, stats) - - case GetTxStatusMsg: - if pm.txpool == nil { - return errResp(ErrUnexpectedResponse, "") - } - // Transactions arrived, parse all of them and deliver to the pool - var req struct { - ReqID uint64 - Hashes []common.Hash - } - if err := msg.Decode(&req); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - reqCnt := len(req.Hashes) - if reject(uint64(reqCnt), MaxTxStatus) { - return errResp(ErrRequestRejected, "") - } - bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost) - pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost) - - return p.SendTxStatus(req.ReqID, bv, pm.txStatus(req.Hashes)) - - case TxStatusMsg: - if pm.odr == nil { - return errResp(ErrUnexpectedResponse, "") - } - - p.Log().Trace("Received tx status response") - var resp struct { - ReqID, BV uint64 - Status []txStatus - } - if err := msg.Decode(&resp); err != nil { - return errResp(ErrDecode, "msg %v: %v", msg, err) - } - - p.fcServer.GotReply(resp.ReqID, resp.BV) - - default: - p.Log().Trace("Received unknown message", "code", msg.Code) - return errResp(ErrInvalidMsgCode, "%v", msg.Code) - } - - if deliverMsg != nil { - err := pm.retriever.deliver(p, deliverMsg) - if err != nil { - p.responseErrors++ - if p.responseErrors > maxResponseErrors { - return err - } - } - } - return nil -} - -// getAccount retrieves an account from the state based at root. -func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (state.Account, error) { - trie, err := trie.New(root, statedb.Database().TrieDB()) - if err != nil { - return state.Account{}, err - } - blob, err := trie.TryGet(hash[:]) - if err != nil { - return state.Account{}, err - } - var account state.Account - if err = rlp.DecodeBytes(blob, &account); err != nil { - return state.Account{}, err - } - return account, nil -} - -// getHelperTrie returns the post-processed trie root for the given trie ID and section index -func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) { - switch id { - case htCanonical: - idxV1 := (idx+1)*(pm.iConfig.PairChtSize/pm.iConfig.ChtSize) - 1 - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idxV1+1)*pm.iConfig.ChtSize-1) - return light.GetChtRoot(pm.chainDb, idxV1, sectionHead), light.ChtTablePrefix - case htBloomBits: - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.iConfig.BloomTrieSize-1) - return light.GetBloomTrieRoot(pm.chainDb, idx, sectionHead), light.BloomTrieTablePrefix - } - return common.Hash{}, "" -} - -// getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request -func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte { - if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { - blockNum := binary.BigEndian.Uint64(req.Key) - hash := rawdb.ReadCanonicalHash(pm.chainDb, blockNum) - return rawdb.ReadHeaderRLP(pm.chainDb, hash, blockNum) - } - return nil -} - -func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus { - stats := make([]txStatus, len(hashes)) - for i, stat := range pm.txpool.Status(hashes) { - // Save the status we've got from the transaction pool - stats[i].Status = stat - - // If the transaction is unknown to the pool, try looking it up locally - if stat == core.TxStatusUnknown { - if block, number, index := rawdb.ReadTxLookupEntry(pm.chainDb, hashes[i]); block != (common.Hash{}) { - stats[i].Status = core.TxStatusIncluded - stats[i].Lookup = &rawdb.TxLookupEntry{BlockHash: block, BlockIndex: number, Index: index} - } - } - } - return stats -} - -// isULCEnabled returns true if we can use ULC -func (pm *ProtocolManager) isULCEnabled() bool { - if pm.ulc == nil || len(pm.ulc.trustedKeys) == 0 { - return false - } - return true -} - -// downloaderPeerNotify implements peerSetNotify -type downloaderPeerNotify ProtocolManager - -type peerConnection struct { - manager *ProtocolManager - peer *peer -} - -func (pc *peerConnection) Head() (common.Hash, *big.Int) { - return pc.peer.HeadAndTd() -} - -func (pc *peerConnection) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool) error { - reqID := genReqID() - rq := &distReq{ - getCost: func(dp distPeer) uint64 { - peer := dp.(*peer) - return peer.GetRequestCost(GetBlockHeadersMsg, amount) - }, - canSend: func(dp distPeer) bool { - return dp.(*peer) == pc.peer - }, - request: func(dp distPeer) func() { - peer := dp.(*peer) - cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) - peer.fcServer.QueueRequest(reqID, cost) - return func() { peer.RequestHeadersByHash(reqID, cost, origin, amount, skip, reverse) } - }, - } - _, ok := <-pc.manager.reqDist.queue(rq) - if !ok { - return light.ErrNoPeers - } - return nil -} - -func (pc *peerConnection) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool) error { - reqID := genReqID() - rq := &distReq{ - getCost: func(dp distPeer) uint64 { - peer := dp.(*peer) - return peer.GetRequestCost(GetBlockHeadersMsg, amount) - }, - canSend: func(dp distPeer) bool { - p := dp.(*peer) - return p == pc.peer - }, - request: func(dp distPeer) func() { - peer := dp.(*peer) - cost := peer.GetRequestCost(GetBlockHeadersMsg, amount) - peer.fcServer.QueueRequest(reqID, cost) - return func() { peer.RequestHeadersByNumber(reqID, cost, origin, amount, skip, reverse) } - }, - } - _, ok := <-pc.manager.reqDist.queue(rq) - if !ok { - return light.ErrNoPeers - } - return nil -} - -func (d *downloaderPeerNotify) registerPeer(p *peer) { - pm := (*ProtocolManager)(d) - pc := &peerConnection{ - manager: pm, - peer: p, - } - pm.downloader.RegisterLightPeer(p.id, ethVersion, pc) -} - -func (d *downloaderPeerNotify) unregisterPeer(p *peer) { - pm := (*ProtocolManager)(d) - if pm.ulc == nil || p.isTrusted { - pm.downloader.UnregisterPeer(p.id) - } -} diff --git a/vendor/github.com/ethereum/go-ethereum/les/metrics.go b/vendor/github.com/ethereum/go-ethereum/les/metrics.go index c282a62a1..9ef8c3651 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/les/metrics.go @@ -22,46 +22,91 @@ import ( ) var ( - /* propTxnInPacketsMeter = metrics.NewMeter("eth/prop/txns/in/packets") - propTxnInTrafficMeter = metrics.NewMeter("eth/prop/txns/in/traffic") - propTxnOutPacketsMeter = metrics.NewMeter("eth/prop/txns/out/packets") - propTxnOutTrafficMeter = metrics.NewMeter("eth/prop/txns/out/traffic") - propHashInPacketsMeter = metrics.NewMeter("eth/prop/hashes/in/packets") - propHashInTrafficMeter = metrics.NewMeter("eth/prop/hashes/in/traffic") - propHashOutPacketsMeter = metrics.NewMeter("eth/prop/hashes/out/packets") - propHashOutTrafficMeter = metrics.NewMeter("eth/prop/hashes/out/traffic") - propBlockInPacketsMeter = metrics.NewMeter("eth/prop/blocks/in/packets") - propBlockInTrafficMeter = metrics.NewMeter("eth/prop/blocks/in/traffic") - propBlockOutPacketsMeter = metrics.NewMeter("eth/prop/blocks/out/packets") - propBlockOutTrafficMeter = metrics.NewMeter("eth/prop/blocks/out/traffic") - reqHashInPacketsMeter = metrics.NewMeter("eth/req/hashes/in/packets") - reqHashInTrafficMeter = metrics.NewMeter("eth/req/hashes/in/traffic") - reqHashOutPacketsMeter = metrics.NewMeter("eth/req/hashes/out/packets") - reqHashOutTrafficMeter = metrics.NewMeter("eth/req/hashes/out/traffic") - reqBlockInPacketsMeter = metrics.NewMeter("eth/req/blocks/in/packets") - reqBlockInTrafficMeter = metrics.NewMeter("eth/req/blocks/in/traffic") - reqBlockOutPacketsMeter = metrics.NewMeter("eth/req/blocks/out/packets") - reqBlockOutTrafficMeter = metrics.NewMeter("eth/req/blocks/out/traffic") - reqHeaderInPacketsMeter = metrics.NewMeter("eth/req/headers/in/packets") - reqHeaderInTrafficMeter = metrics.NewMeter("eth/req/headers/in/traffic") - reqHeaderOutPacketsMeter = metrics.NewMeter("eth/req/headers/out/packets") - reqHeaderOutTrafficMeter = metrics.NewMeter("eth/req/headers/out/traffic") - reqBodyInPacketsMeter = metrics.NewMeter("eth/req/bodies/in/packets") - reqBodyInTrafficMeter = metrics.NewMeter("eth/req/bodies/in/traffic") - reqBodyOutPacketsMeter = metrics.NewMeter("eth/req/bodies/out/packets") - reqBodyOutTrafficMeter = metrics.NewMeter("eth/req/bodies/out/traffic") - reqStateInPacketsMeter = metrics.NewMeter("eth/req/states/in/packets") - reqStateInTrafficMeter = metrics.NewMeter("eth/req/states/in/traffic") - reqStateOutPacketsMeter = metrics.NewMeter("eth/req/states/out/packets") - reqStateOutTrafficMeter = metrics.NewMeter("eth/req/states/out/traffic") - reqReceiptInPacketsMeter = metrics.NewMeter("eth/req/receipts/in/packets") - reqReceiptInTrafficMeter = metrics.NewMeter("eth/req/receipts/in/traffic") - reqReceiptOutPacketsMeter = metrics.NewMeter("eth/req/receipts/out/packets") - reqReceiptOutTrafficMeter = metrics.NewMeter("eth/req/receipts/out/traffic")*/ - miscInPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets", nil) - miscInTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic", nil) - miscOutPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets", nil) - miscOutTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic", nil) + miscInPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/total", nil) + miscInTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/total", nil) + miscInHeaderPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/header", nil) + miscInHeaderTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/header", nil) + miscInBodyPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/body", nil) + miscInBodyTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/body", nil) + miscInCodePacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/code", nil) + miscInCodeTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/code", nil) + miscInReceiptPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/receipt", nil) + miscInReceiptTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/receipt", nil) + miscInTrieProofPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/proof", nil) + miscInTrieProofTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/proof", nil) + miscInHelperTriePacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/helperTrie", nil) + miscInHelperTrieTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/helperTrie", nil) + miscInTxsPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/txs", nil) + miscInTxsTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/txs", nil) + miscInTxStatusPacketsMeter = metrics.NewRegisteredMeter("les/misc/in/packets/txStatus", nil) + miscInTxStatusTrafficMeter = metrics.NewRegisteredMeter("les/misc/in/traffic/txStatus", nil) + + miscOutPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/total", nil) + miscOutTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/total", nil) + miscOutHeaderPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/header", nil) + miscOutHeaderTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/header", nil) + miscOutBodyPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/body", nil) + miscOutBodyTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/body", nil) + miscOutCodePacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/code", nil) + miscOutCodeTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/code", nil) + miscOutReceiptPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/receipt", nil) + miscOutReceiptTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/receipt", nil) + miscOutTrieProofPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/proof", nil) + miscOutTrieProofTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/proof", nil) + miscOutHelperTriePacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/helperTrie", nil) + miscOutHelperTrieTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/helperTrie", nil) + miscOutTxsPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/txs", nil) + miscOutTxsTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/txs", nil) + miscOutTxStatusPacketsMeter = metrics.NewRegisteredMeter("les/misc/out/packets/txStatus", nil) + miscOutTxStatusTrafficMeter = metrics.NewRegisteredMeter("les/misc/out/traffic/txStatus", nil) + + miscServingTimeHeaderTimer = metrics.NewRegisteredTimer("les/misc/serve/header", nil) + miscServingTimeBodyTimer = metrics.NewRegisteredTimer("les/misc/serve/body", nil) + miscServingTimeCodeTimer = metrics.NewRegisteredTimer("les/misc/serve/code", nil) + miscServingTimeReceiptTimer = metrics.NewRegisteredTimer("les/misc/serve/receipt", nil) + miscServingTimeTrieProofTimer = metrics.NewRegisteredTimer("les/misc/serve/proof", nil) + miscServingTimeHelperTrieTimer = metrics.NewRegisteredTimer("les/misc/serve/helperTrie", nil) + miscServingTimeTxTimer = metrics.NewRegisteredTimer("les/misc/serve/txs", nil) + miscServingTimeTxStatusTimer = metrics.NewRegisteredTimer("les/misc/serve/txStatus", nil) + + connectionTimer = metrics.NewRegisteredTimer("les/connection/duration", nil) + serverConnectionGauge = metrics.NewRegisteredGauge("les/connection/server", nil) + clientConnectionGauge = metrics.NewRegisteredGauge("les/connection/client", nil) + + totalCapacityGauge = metrics.NewRegisteredGauge("les/server/totalCapacity", nil) + totalRechargeGauge = metrics.NewRegisteredGauge("les/server/totalRecharge", nil) + totalConnectedGauge = metrics.NewRegisteredGauge("les/server/totalConnected", nil) + blockProcessingTimer = metrics.NewRegisteredTimer("les/server/blockProcessingTime", nil) + + requestServedMeter = metrics.NewRegisteredMeter("les/server/req/avgServedTime", nil) + requestServedTimer = metrics.NewRegisteredTimer("les/server/req/servedTime", nil) + requestEstimatedMeter = metrics.NewRegisteredMeter("les/server/req/avgEstimatedTime", nil) + requestEstimatedTimer = metrics.NewRegisteredTimer("les/server/req/estimatedTime", nil) + relativeCostHistogram = metrics.NewRegisteredHistogram("les/server/req/relative", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostHeaderHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/header", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostBodyHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/body", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostReceiptHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/receipt", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostCodeHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/code", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostProofHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/proof", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostHelperProofHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/helperTrie", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostSendTxHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/txs", nil, metrics.NewExpDecaySample(1028, 0.015)) + relativeCostTxStatusHistogram = metrics.NewRegisteredHistogram("les/server/req/relative/txStatus", nil, metrics.NewExpDecaySample(1028, 0.015)) + + globalFactorGauge = metrics.NewRegisteredGauge("les/server/globalFactor", nil) + recentServedGauge = metrics.NewRegisteredGauge("les/server/recentRequestServed", nil) + recentEstimatedGauge = metrics.NewRegisteredGauge("les/server/recentRequestEstimated", nil) + sqServedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/served", nil) + sqQueuedGauge = metrics.NewRegisteredGauge("les/server/servingQueue/queued", nil) + + clientConnectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/connected", nil) + clientRejectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/rejected", nil) + clientKickedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/kicked", nil) + clientDisconnectedMeter = metrics.NewRegisteredMeter("les/server/clientEvent/disconnected", nil) + clientFreezeMeter = metrics.NewRegisteredMeter("les/server/clientEvent/freeze", nil) + clientErrorMeter = metrics.NewRegisteredMeter("les/server/clientEvent/error", nil) + + requestRTT = metrics.NewRegisteredTimer("les/client/req/rtt", nil) + requestSendDelay = metrics.NewRegisteredTimer("les/client/req/sendDelay", nil) ) // meteredMsgReadWriter is a wrapper around a p2p.MsgReadWriter, capable of @@ -73,17 +118,11 @@ type meteredMsgReadWriter struct { // newMeteredMsgWriter wraps a p2p MsgReadWriter with metering support. If the // metrics system is disabled, this function returns the original object. -func newMeteredMsgWriter(rw p2p.MsgReadWriter) p2p.MsgReadWriter { +func newMeteredMsgWriter(rw p2p.MsgReadWriter, version int) p2p.MsgReadWriter { if !metrics.Enabled { return rw } - return &meteredMsgReadWriter{MsgReadWriter: rw} -} - -// Init sets the protocol version used by the stream to know which meters to -// increment in case of overlapping message ids between protocol versions. -func (rw *meteredMsgReadWriter) Init(version int) { - rw.version = version + return &meteredMsgReadWriter{MsgReadWriter: rw, version: version} } func (rw *meteredMsgReadWriter) ReadMsg() (p2p.Msg, error) { diff --git a/vendor/github.com/ethereum/go-ethereum/les/odr.go b/vendor/github.com/ethereum/go-ethereum/les/odr.go index f7592354d..136ecf4df 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/odr.go +++ b/vendor/github.com/ethereum/go-ethereum/les/odr.go @@ -18,7 +18,9 @@ package les import ( "context" + "time" + "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/light" @@ -84,10 +86,9 @@ const ( MsgBlockBodies = iota MsgCode MsgReceipts - MsgProofsV1 MsgProofsV2 - MsgHeaderProofs MsgHelperTrieProofs + MsgTxStatus ) // Msg encodes a LES message that delivers reply data for a request @@ -109,7 +110,7 @@ func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err erro }, canSend: func(dp distPeer) bool { p := dp.(*peer) - if !p.isOnlyAnnounce { + if !p.onlyAnnounce { return lreq.CanSend(p) } return false @@ -117,14 +118,15 @@ func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err erro request: func(dp distPeer) func() { p := dp.(*peer) cost := lreq.GetCost(p) - p.fcServer.QueueRequest(reqID, cost) + p.fcServer.QueuedRequest(reqID, cost) return func() { lreq.Request(reqID, p) } }, } - + sent := mclock.Now() if err = odr.retriever.retrieve(ctx, reqID, rq, func(p distPeer, msg *Msg) error { return lreq.Validate(odr.db, msg) }, odr.stop); err == nil { // retrieved from network, store in db req.StoreResult(odr.db) + requestRTT.Update(time.Duration(mclock.Now() - sent)) } else { log.Debug("Failed to retrieve data from network", "err", err) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/odr_requests.go b/vendor/github.com/ethereum/go-ethereum/les/odr_requests.go index 0f2e5dd9e..3c4dd7090 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/odr_requests.go +++ b/vendor/github.com/ethereum/go-ethereum/les/odr_requests.go @@ -14,8 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package light implements on-demand retrieval capable state and chain objects -// for the Ethereum Light Client. package les import ( @@ -68,6 +66,8 @@ func LesRequest(req light.OdrRequest) LesOdrRequest { return (*ChtRequest)(r) case *light.BloomRequest: return (*BloomRequest)(r) + case *light.TxStatusRequest: + return (*TxStatusRequest)(r) default: return nil } @@ -166,11 +166,13 @@ func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error { receipt := receipts[0] // Retrieve our stored header and validate receipt content against it - header := rawdb.ReadHeader(db, r.Hash, r.Number) - if header == nil { + if r.Header == nil { + r.Header = rawdb.ReadHeader(db, r.Hash, r.Number) + } + if r.Header == nil { return errHeaderUnavailable } - if header.ReceiptHash != types.DeriveSha(receipt) { + if r.Header.ReceiptHash != types.DeriveSha(receipt) { return errReceiptHashMismatch } // Validations passed, store and return @@ -190,14 +192,7 @@ type TrieRequest light.TrieRequest // GetCost returns the cost of the given ODR request according to the serving // peer's cost table (implementation of LesOdrRequest) func (r *TrieRequest) GetCost(peer *peer) uint64 { - switch peer.version { - case lpv1: - return peer.GetRequestCost(GetProofsV1Msg, 1) - case lpv2: - return peer.GetRequestCost(GetProofsV2Msg, 1) - default: - panic(nil) - } + return peer.GetRequestCost(GetProofsV2Msg, 1) } // CanSend tells if a certain peer is suitable for serving the given request @@ -222,38 +217,22 @@ func (r *TrieRequest) Request(reqID uint64, peer *peer) error { func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error { log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key) - switch msg.MsgType { - case MsgProofsV1: - proofs := msg.Obj.([]light.NodeList) - if len(proofs) != 1 { - return errInvalidEntryCount - } - nodeSet := proofs[0].NodeSet() - // Verify the proof and store if checks out - if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, nodeSet); err != nil { - return fmt.Errorf("merkle proof verification failed: %v", err) - } - r.Proof = nodeSet - return nil - - case MsgProofsV2: - proofs := msg.Obj.(light.NodeList) - // Verify the proof and store if checks out - nodeSet := proofs.NodeSet() - reads := &readTraceDB{db: nodeSet} - if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil { - return fmt.Errorf("merkle proof verification failed: %v", err) - } - // check if all nodes have been read by VerifyProof - if len(reads.reads) != nodeSet.KeyCount() { - return errUselessNodes - } - r.Proof = nodeSet - return nil - - default: + if msg.MsgType != MsgProofsV2 { return errInvalidMessageType } + proofs := msg.Obj.(light.NodeList) + // Verify the proof and store if checks out + nodeSet := proofs.NodeSet() + reads := &readTraceDB{db: nodeSet} + if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil { + return fmt.Errorf("merkle proof verification failed: %v", err) + } + // check if all nodes have been read by VerifyProof + if len(reads.reads) != nodeSet.KeyCount() { + return errUselessNodes + } + r.Proof = nodeSet + return nil } type CodeReq struct { @@ -332,32 +311,13 @@ type HelperTrieResps struct { // describes all responses, not just a single one AuxData [][]byte } -// legacy LES/1 -type ChtReq struct { - ChtNum, BlockNum uint64 - FromLevel uint -} - -// legacy LES/1 -type ChtResp struct { - Header *types.Header - Proof []rlp.RawValue -} - // ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface type ChtRequest light.ChtRequest // GetCost returns the cost of the given ODR request according to the serving // peer's cost table (implementation of LesOdrRequest) func (r *ChtRequest) GetCost(peer *peer) uint64 { - switch peer.version { - case lpv1: - return peer.GetRequestCost(GetHeaderProofsMsg, 1) - case lpv2: - return peer.GetRequestCost(GetHelperTrieProofsMsg, 1) - default: - panic(nil) - } + return peer.GetRequestCost(GetHelperTrieProofsMsg, 1) } // CanSend tells if a certain peer is suitable for serving the given request @@ -365,7 +325,11 @@ func (r *ChtRequest) CanSend(peer *peer) bool { peer.lock.RLock() defer peer.lock.RUnlock() - return peer.headInfo.Number >= r.Config.ChtConfirms && r.ChtNum <= (peer.headInfo.Number-r.Config.ChtConfirms)/r.Config.ChtSize + if r.Untrusted { + return peer.headInfo.Number >= r.BlockNum && peer.id == r.PeerId + } else { + return peer.headInfo.Number >= r.Config.ChtConfirms && r.ChtNum <= (peer.headInfo.Number-r.Config.ChtConfirms)/r.Config.ChtSize + } } // Request sends an ODR request to the LES network (implementation of LesOdrRequest) @@ -379,21 +343,7 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error { Key: encNum[:], AuxReq: auxHeader, } - switch peer.version { - case lpv1: - var reqsV1 ChtReq - if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 { - return fmt.Errorf("Request invalid in LES/1 mode") - } - blockNum := binary.BigEndian.Uint64(req.Key) - // convert HelperTrie request to old CHT request - reqsV1 = ChtReq{ChtNum: (req.TrieIdx + 1) * (r.Config.ChtSize / r.Config.PairChtSize), BlockNum: blockNum, FromLevel: req.FromLevel} - return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []ChtReq{reqsV1}) - case lpv2: - return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req}) - default: - panic(nil) - } + return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req}) } // Valid processes an ODR request reply message from the LES network @@ -402,49 +352,28 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error { func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum) - switch msg.MsgType { - case MsgHeaderProofs: // LES/1 backwards compatibility - proofs := msg.Obj.([]ChtResp) - if len(proofs) != 1 { - return errInvalidEntryCount - } - proof := proofs[0] + if msg.MsgType != MsgHelperTrieProofs { + return errInvalidMessageType + } + resp := msg.Obj.(HelperTrieResps) + if len(resp.AuxData) != 1 { + return errInvalidEntryCount + } + nodeSet := resp.Proofs.NodeSet() + headerEnc := resp.AuxData[0] + if len(headerEnc) == 0 { + return errHeaderUnavailable + } + header := new(types.Header) + if err := rlp.DecodeBytes(headerEnc, header); err != nil { + return errHeaderUnavailable + } - // Verify the CHT - var encNumber [8]byte - binary.BigEndian.PutUint64(encNumber[:], r.BlockNum) - - value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], light.NodeList(proof.Proof).NodeSet()) - if err != nil { - return err - } - var node light.ChtNode - if err := rlp.DecodeBytes(value, &node); err != nil { - return err - } - if node.Hash != proof.Header.Hash() { - return errCHTHashMismatch - } - // Verifications passed, store and return - r.Header = proof.Header - r.Proof = light.NodeList(proof.Proof).NodeSet() - r.Td = node.Td - case MsgHelperTrieProofs: - resp := msg.Obj.(HelperTrieResps) - if len(resp.AuxData) != 1 { - return errInvalidEntryCount - } - nodeSet := resp.Proofs.NodeSet() - headerEnc := resp.AuxData[0] - if len(headerEnc) == 0 { - return errHeaderUnavailable - } - header := new(types.Header) - if err := rlp.DecodeBytes(headerEnc, header); err != nil { - return errHeaderUnavailable - } - - // Verify the CHT + // Verify the CHT + // Note: For untrusted CHT request, there is no proof response but + // header data. + var node light.ChtNode + if !r.Untrusted { var encNumber [8]byte binary.BigEndian.PutUint64(encNumber[:], r.BlockNum) @@ -457,7 +386,6 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { return errUselessNodes } - var node light.ChtNode if err := rlp.DecodeBytes(value, &node); err != nil { return err } @@ -467,13 +395,12 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { if r.BlockNum != header.Number.Uint64() { return errCHTNumberMismatch } - // Verifications passed, store and return - r.Header = header - r.Proof = nodeSet - r.Td = node.Td - default: - return errInvalidMessageType } + // Verifications passed, store and return + r.Header = header + r.Proof = nodeSet + r.Td = node.Td // For untrusted request, td here is nil, todo improve the les/2 protocol + return nil } @@ -557,10 +484,48 @@ func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error { return nil } +// TxStatusRequest is the ODR request type for transaction status +type TxStatusRequest light.TxStatusRequest + +// GetCost returns the cost of the given ODR request according to the serving +// peer's cost table (implementation of LesOdrRequest) +func (r *TxStatusRequest) GetCost(peer *peer) uint64 { + return peer.GetRequestCost(GetTxStatusMsg, len(r.Hashes)) +} + +// CanSend tells if a certain peer is suitable for serving the given request +func (r *TxStatusRequest) CanSend(peer *peer) bool { + return peer.version >= lpv2 +} + +// Request sends an ODR request to the LES network (implementation of LesOdrRequest) +func (r *TxStatusRequest) Request(reqID uint64, peer *peer) error { + peer.Log().Debug("Requesting transaction status", "count", len(r.Hashes)) + return peer.RequestTxStatus(reqID, r.GetCost(peer), r.Hashes) +} + +// Valid processes an ODR request reply message from the LES network +// returns true and stores results in memory if the message was a valid reply +// to the request (implementation of LesOdrRequest) +func (r *TxStatusRequest) Validate(db ethdb.Database, msg *Msg) error { + log.Debug("Validating transaction status", "count", len(r.Hashes)) + + // Ensure we have a correct message with a single block body + if msg.MsgType != MsgTxStatus { + return errInvalidMessageType + } + status := msg.Obj.([]light.TxStatus) + if len(status) != len(r.Hashes) { + return errInvalidEntryCount + } + r.Status = status + return nil +} + // readTraceDB stores the keys of database reads. We use this to check that received node // sets contain only the trie nodes necessary to make proofs pass. type readTraceDB struct { - db trie.DatabaseReader + db ethdb.KeyValueReader reads map[string]struct{} } diff --git a/vendor/github.com/ethereum/go-ethereum/les/peer.go b/vendor/github.com/ethereum/go-ethereum/les/peer.go index bab90a366..ab5b30a65 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/les/peer.go @@ -14,33 +14,53 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( "errors" "fmt" "math/big" + "math/rand" + "net" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) var ( - errClosed = errors.New("peer set is closed") - errAlreadyRegistered = errors.New("peer is already registered") - errNotRegistered = errors.New("peer is not registered") - errInvalidHelpTrieReq = errors.New("invalid help trie request") + errClosed = errors.New("peer set is closed") + errAlreadyRegistered = errors.New("peer is already registered") + errNotRegistered = errors.New("peer is not registered") ) -const maxResponseErrors = 50 // number of invalid responses tolerated (makes the protocol less brittle but still avoids spam) +const ( + maxRequestErrors = 20 // number of invalid requests tolerated (makes the protocol less brittle but still avoids spam) + maxResponseErrors = 50 // number of invalid responses tolerated (makes the protocol less brittle but still avoids spam) +) + +// capacity limitation for parameter updates +const ( + allowedUpdateBytes = 100000 // initial/maximum allowed update size + allowedUpdateRate = time.Millisecond * 10 // time constant for recharging one byte of allowance +) + +const ( + freezeTimeBase = time.Millisecond * 700 // fixed component of client freeze time + freezeTimeRandom = time.Millisecond * 600 // random component of client freeze time + freezeCheckPeriod = time.Millisecond * 100 // buffer value recheck period after initial freeze time has elapsed +) // if the total encoded size of a sent transaction batch is over txSizeCostLimit // per transaction then the request cost is calculated as proportional to the @@ -55,7 +75,6 @@ const ( type peer struct { *p2p.Peer - rw p2p.MsgReadWriter version int // Protocol version negotiated @@ -63,43 +82,149 @@ type peer struct { announceType uint64 + // Checkpoint relative fields + checkpoint params.TrustedCheckpoint + checkpointNumber uint64 + id string headInfo *announceData lock sync.RWMutex - announceChn chan announceData - sendQueue *execQueue + sendQueue *execQueue + + errCh chan error + + // responseLock ensures that responses are queued in the same order as + // RequestProcessed is called + responseLock sync.Mutex + responseCount uint64 + invalidCount uint32 poolEntry *poolEntry hasBlock func(common.Hash, uint64, bool) bool responseErrors int + updateCounter uint64 + updateTime mclock.AbsTime + frozen uint32 // 1 if client is in frozen state - fcClient *flowcontrol.ClientNode // nil if the peer is server only - fcServer *flowcontrol.ServerNode // nil if the peer is client only - fcServerParams *flowcontrol.ServerParams - fcCosts requestCostTable + fcClient *flowcontrol.ClientNode // nil if the peer is server only + fcServer *flowcontrol.ServerNode // nil if the peer is client only + fcParams flowcontrol.ServerParams + fcCosts requestCostTable - isTrusted bool - isOnlyAnnounce bool + trusted bool + onlyAnnounce bool + chainSince, chainRecent uint64 + stateSince, stateRecent uint64 } -func newPeer(version int, network uint64, isTrusted bool, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { - id := p.ID() - +func newPeer(version int, network uint64, trusted bool, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { return &peer{ - Peer: p, - rw: rw, - version: version, - network: network, - id: fmt.Sprintf("%x", id[:8]), - announceChn: make(chan announceData, 20), - isTrusted: isTrusted, + Peer: p, + rw: rw, + version: version, + network: network, + id: peerIdToString(p.ID()), + trusted: trusted, + errCh: make(chan error, 1), } } +// peerIdToString converts enode.ID to a string form +func peerIdToString(id enode.ID) string { + return fmt.Sprintf("%x", id.Bytes()) +} + +// freeClientId returns a string identifier for the peer. Multiple peers with the +// same identifier can not be connected in free mode simultaneously. +func (p *peer) freeClientId() string { + if addr, ok := p.RemoteAddr().(*net.TCPAddr); ok { + if addr.IP.IsLoopback() { + // using peer id instead of loopback ip address allows multiple free + // connections from local machine to own server + return p.id + } else { + return addr.IP.String() + } + } + return p.id +} + +// rejectUpdate returns true if a parameter update has to be rejected because +// the size and/or rate of updates exceed the capacity limitation +func (p *peer) rejectUpdate(size uint64) bool { + now := mclock.Now() + if p.updateCounter == 0 { + p.updateTime = now + } else { + dt := now - p.updateTime + r := uint64(dt / mclock.AbsTime(allowedUpdateRate)) + if p.updateCounter > r { + p.updateCounter -= r + p.updateTime += mclock.AbsTime(allowedUpdateRate * time.Duration(r)) + } else { + p.updateCounter = 0 + p.updateTime = now + } + } + p.updateCounter += size + return p.updateCounter > allowedUpdateBytes +} + +// freezeClient temporarily puts the client in a frozen state which means all +// unprocessed and subsequent requests are dropped. Unfreezing happens automatically +// after a short time if the client's buffer value is at least in the slightly positive +// region. The client is also notified about being frozen/unfrozen with a Stop/Resume +// message. +func (p *peer) freezeClient() { + if p.version < lpv3 { + // if Stop/Resume is not supported then just drop the peer after setting + // its frozen status permanently + atomic.StoreUint32(&p.frozen, 1) + p.Peer.Disconnect(p2p.DiscUselessPeer) + return + } + if atomic.SwapUint32(&p.frozen, 1) == 0 { + go func() { + p.SendStop() + time.Sleep(freezeTimeBase + time.Duration(rand.Int63n(int64(freezeTimeRandom)))) + for { + bufValue, bufLimit := p.fcClient.BufferStatus() + if bufLimit == 0 { + return + } + if bufValue <= bufLimit/8 { + time.Sleep(freezeCheckPeriod) + } else { + atomic.StoreUint32(&p.frozen, 0) + p.SendResume(bufValue) + break + } + } + }() + } +} + +// freezeServer processes Stop/Resume messages from the given server +func (p *peer) freezeServer(frozen bool) { + var f uint32 + if frozen { + f = 1 + } + if atomic.SwapUint32(&p.frozen, f) != f && frozen { + p.sendQueue.clear() + } +} + +// isFrozen returns true if the client is frozen or the server has put our +// client in frozen state +func (p *peer) isFrozen() bool { + return atomic.LoadUint32(&p.frozen) != 0 +} + func (p *peer) canQueue() bool { - return p.sendQueue.canQueue() + return p.sendQueue.canQueue() && !p.isFrozen() } func (p *peer) queueSend(f func()) { @@ -152,6 +277,25 @@ func (p *peer) waitBefore(maxCost uint64) (time.Duration, float64) { return p.fcServer.CanSend(maxCost) } +// updateCapacity updates the request serving capacity assigned to a given client +// and also sends an announcement about the updated flow control parameters +func (p *peer) updateCapacity(cap uint64) { + p.responseLock.Lock() + defer p.responseLock.Unlock() + + p.fcParams = flowcontrol.ServerParams{MinRecharge: cap, BufLimit: cap * bufLimitRatio} + p.fcClient.UpdateParams(p.fcParams) + var kvList keyValueList + kvList = kvList.add("flowControl/MRR", cap) + kvList = kvList.add("flowControl/BL", cap*bufLimitRatio) + p.queueSend(func() { p.SendAnnounce(announceData{Update: kvList}) }) +} + +func (p *peer) responseID() uint64 { + p.responseCount += 1 + return p.responseCount +} + func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) error { type req struct { ReqID uint64 @@ -160,12 +304,27 @@ func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) return p2p.Send(w, msgcode, req{reqID, data}) } -func sendResponse(w p2p.MsgWriter, msgcode, reqID, bv uint64, data interface{}) error { +// reply struct represents a reply with the actual data already RLP encoded and +// only the bv (buffer value) missing. This allows the serving mechanism to +// calculate the bv value which depends on the data size before sending the reply. +type reply struct { + w p2p.MsgWriter + msgcode, reqID uint64 + data rlp.RawValue +} + +// send sends the reply with the calculated buffer value +func (r *reply) send(bv uint64) error { type resp struct { ReqID, BV uint64 - Data interface{} + Data rlp.RawValue } - return p2p.Send(w, msgcode, resp{reqID, bv, data}) + return p2p.Send(r.w, r.msgcode, resp{r.reqID, bv, r.data}) +} + +// size returns the RLP encoded size of the message data +func (r *reply) size() uint32 { + return uint32(len(r.data)) } func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 { @@ -177,8 +336,8 @@ func (p *peer) GetRequestCost(msgcode uint64, amount int) uint64 { return 0 } cost := costs.baseCost + costs.reqCost*uint64(amount) - if cost > p.fcServerParams.BufLimit { - cost = p.fcServerParams.BufLimit + if cost > p.fcParams.BufLimit { + cost = p.fcParams.BufLimit } return cost } @@ -187,17 +346,7 @@ func (p *peer) GetTxRelayCost(amount, size int) uint64 { p.lock.RLock() defer p.lock.RUnlock() - var msgcode uint64 - switch p.version { - case lpv1: - msgcode = SendTxMsg - case lpv2: - msgcode = SendTxV2Msg - default: - panic(nil) - } - - costs := p.fcCosts[msgcode] + costs := p.fcCosts[SendTxV2Msg] if costs == nil { return 0 } @@ -207,18 +356,30 @@ func (p *peer) GetTxRelayCost(amount, size int) uint64 { cost = sizeCost } - if cost > p.fcServerParams.BufLimit { - cost = p.fcServerParams.BufLimit + if cost > p.fcParams.BufLimit { + cost = p.fcParams.BufLimit } return cost } // HasBlock checks if the peer has a given block func (p *peer) HasBlock(hash common.Hash, number uint64, hasState bool) bool { + var head, since, recent uint64 p.lock.RLock() + if p.headInfo != nil { + head = p.headInfo.Number + } + if hasState { + since = p.stateSince + recent = p.stateRecent + } else { + since = p.chainSince + recent = p.chainRecent + } hasBlock := p.hasBlock p.lock.RUnlock() - return hasBlock != nil && hasBlock(hash, number, hasState) + + return head >= number && number >= since && (recent == 0 || number+recent+4 > head) && hasBlock != nil && hasBlock(hash, number, hasState) } // SendAnnounce announces the availability of a number of blocks through @@ -227,52 +388,59 @@ func (p *peer) SendAnnounce(request announceData) error { return p2p.Send(p.rw, AnnounceMsg, request) } -// SendBlockHeaders sends a batch of block headers to the remote peer. -func (p *peer) SendBlockHeaders(reqID, bv uint64, headers []*types.Header) error { - return sendResponse(p.rw, BlockHeadersMsg, reqID, bv, headers) +// SendStop notifies the client about being in frozen state +func (p *peer) SendStop() error { + return p2p.Send(p.rw, StopMsg, struct{}{}) } -// SendBlockBodiesRLP sends a batch of block contents to the remote peer from +// SendResume notifies the client about getting out of frozen state +func (p *peer) SendResume(bv uint64) error { + return p2p.Send(p.rw, ResumeMsg, bv) +} + +// ReplyBlockHeaders creates a reply with a batch of block headers +func (p *peer) ReplyBlockHeaders(reqID uint64, headers []*types.Header) *reply { + data, _ := rlp.EncodeToBytes(headers) + return &reply{p.rw, BlockHeadersMsg, reqID, data} +} + +// ReplyBlockBodiesRLP creates a reply with a batch of block contents from // an already RLP encoded format. -func (p *peer) SendBlockBodiesRLP(reqID, bv uint64, bodies []rlp.RawValue) error { - return sendResponse(p.rw, BlockBodiesMsg, reqID, bv, bodies) +func (p *peer) ReplyBlockBodiesRLP(reqID uint64, bodies []rlp.RawValue) *reply { + data, _ := rlp.EncodeToBytes(bodies) + return &reply{p.rw, BlockBodiesMsg, reqID, data} } -// SendCodeRLP sends a batch of arbitrary internal data, corresponding to the +// ReplyCode creates a reply with a batch of arbitrary internal data, corresponding to the // hashes requested. -func (p *peer) SendCode(reqID, bv uint64, data [][]byte) error { - return sendResponse(p.rw, CodeMsg, reqID, bv, data) +func (p *peer) ReplyCode(reqID uint64, codes [][]byte) *reply { + data, _ := rlp.EncodeToBytes(codes) + return &reply{p.rw, CodeMsg, reqID, data} } -// SendReceiptsRLP sends a batch of transaction receipts, corresponding to the +// ReplyReceiptsRLP creates a reply with a batch of transaction receipts, corresponding to the // ones requested from an already RLP encoded format. -func (p *peer) SendReceiptsRLP(reqID, bv uint64, receipts []rlp.RawValue) error { - return sendResponse(p.rw, ReceiptsMsg, reqID, bv, receipts) +func (p *peer) ReplyReceiptsRLP(reqID uint64, receipts []rlp.RawValue) *reply { + data, _ := rlp.EncodeToBytes(receipts) + return &reply{p.rw, ReceiptsMsg, reqID, data} } -// SendProofs sends a batch of legacy LES/1 merkle proofs, corresponding to the ones requested. -func (p *peer) SendProofs(reqID, bv uint64, proofs proofsData) error { - return sendResponse(p.rw, ProofsV1Msg, reqID, bv, proofs) +// ReplyProofsV2 creates a reply with a batch of merkle proofs, corresponding to the ones requested. +func (p *peer) ReplyProofsV2(reqID uint64, proofs light.NodeList) *reply { + data, _ := rlp.EncodeToBytes(proofs) + return &reply{p.rw, ProofsV2Msg, reqID, data} } -// SendProofsV2 sends a batch of merkle proofs, corresponding to the ones requested. -func (p *peer) SendProofsV2(reqID, bv uint64, proofs light.NodeList) error { - return sendResponse(p.rw, ProofsV2Msg, reqID, bv, proofs) +// ReplyHelperTrieProofs creates a reply with a batch of HelperTrie proofs, corresponding to the ones requested. +func (p *peer) ReplyHelperTrieProofs(reqID uint64, resp HelperTrieResps) *reply { + data, _ := rlp.EncodeToBytes(resp) + return &reply{p.rw, HelperTrieProofsMsg, reqID, data} } -// SendHeaderProofs sends a batch of legacy LES/1 header proofs, corresponding to the ones requested. -func (p *peer) SendHeaderProofs(reqID, bv uint64, proofs []ChtResp) error { - return sendResponse(p.rw, HeaderProofsMsg, reqID, bv, proofs) -} - -// SendHelperTrieProofs sends a batch of HelperTrie proofs, corresponding to the ones requested. -func (p *peer) SendHelperTrieProofs(reqID, bv uint64, resp HelperTrieResps) error { - return sendResponse(p.rw, HelperTrieProofsMsg, reqID, bv, resp) -} - -// SendTxStatus sends a batch of transaction status records, corresponding to the ones requested. -func (p *peer) SendTxStatus(reqID, bv uint64, stats []txStatus) error { - return sendResponse(p.rw, TxStatusMsg, reqID, bv, stats) +// ReplyTxStatus creates a reply with a batch of transaction status records, corresponding to the ones requested. +func (p *peer) ReplyTxStatus(reqID uint64, stats []light.TxStatus) *reply { + data, _ := rlp.EncodeToBytes(stats) + return &reply{p.rw, TxStatusMsg, reqID, data} } // RequestHeadersByHash fetches a batch of blocks' headers corresponding to the @@ -312,36 +480,13 @@ func (p *peer) RequestReceipts(reqID, cost uint64, hashes []common.Hash) error { // RequestProofs fetches a batch of merkle proofs from a remote node. func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error { p.Log().Debug("Fetching batch of proofs", "count", len(reqs)) - switch p.version { - case lpv1: - return sendRequest(p.rw, GetProofsV1Msg, reqID, cost, reqs) - case lpv2: - return sendRequest(p.rw, GetProofsV2Msg, reqID, cost, reqs) - default: - panic(nil) - } + return sendRequest(p.rw, GetProofsV2Msg, reqID, cost, reqs) } // RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node. -func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, data interface{}) error { - switch p.version { - case lpv1: - reqs, ok := data.([]ChtReq) - if !ok { - return errInvalidHelpTrieReq - } - p.Log().Debug("Fetching batch of header proofs", "count", len(reqs)) - return sendRequest(p.rw, GetHeaderProofsMsg, reqID, cost, reqs) - case lpv2: - reqs, ok := data.([]HelperTrieReq) - if !ok { - return errInvalidHelpTrieReq - } - p.Log().Debug("Fetching batch of HelperTrie proofs", "count", len(reqs)) - return sendRequest(p.rw, GetHelperTrieProofsMsg, reqID, cost, reqs) - default: - panic(nil) - } +func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, reqs []HelperTrieReq) error { + p.Log().Debug("Fetching batch of HelperTrie proofs", "count", len(reqs)) + return sendRequest(p.rw, GetHelperTrieProofsMsg, reqID, cost, reqs) } // RequestTxStatus fetches a batch of transaction status records from a remote node. @@ -350,17 +495,10 @@ func (p *peer) RequestTxStatus(reqID, cost uint64, txHashes []common.Hash) error return sendRequest(p.rw, GetTxStatusMsg, reqID, cost, txHashes) } -// SendTxs sends a batch of transactions to be added to the remote transaction pool. +// SendTxStatus creates a reply with a batch of transactions to be added to the remote transaction pool. func (p *peer) SendTxs(reqID, cost uint64, txs rlp.RawValue) error { - p.Log().Debug("Fetching batch of transactions", "size", len(txs)) - switch p.version { - case lpv1: - return p2p.Send(p.rw, SendTxMsg, txs) // old message format does not include reqID - case lpv2: - return sendRequest(p.rw, SendTxV2Msg, reqID, cost, txs) - default: - panic(nil) - } + p.Log().Debug("Sending batch of transactions", "size", len(txs)) + return sendRequest(p.rw, SendTxV2Msg, reqID, cost, txs) } type keyValueEntry struct { @@ -383,12 +521,14 @@ func (l keyValueList) add(key string, val interface{}) keyValueList { return append(l, entry) } -func (l keyValueList) decode() keyValueMap { +func (l keyValueList) decode() (keyValueMap, uint64) { m := make(keyValueMap) + var size uint64 for _, entry := range l { m[entry.Key] = entry.Value + size += uint64(len(entry.Key)) + uint64(len(entry.Value)) + 8 } - return m + return m, size } func (m keyValueMap) get(key string, val interface{}) error { @@ -437,6 +577,8 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis defer p.lock.Unlock() var send keyValueList + + // Add some basic handshake fields send = send.add("protocolVersion", uint64(p.version)) send = send.add("networkId", p.network) send = send.add("headTd", td) @@ -444,22 +586,47 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis send = send.add("headNum", headNum) send = send.add("genesisHash", genesis) if server != nil { - if !server.onlyAnnounce { - //only announce server. It sends only announse requests + // Add some information which services server can offer. + if !server.config.UltraLightOnlyAnnounce { send = send.add("serveHeaders", nil) send = send.add("serveChainSince", uint64(0)) send = send.add("serveStateSince", uint64(0)) + + // If local ethereum node is running in archive mode, advertise ourselves we have + // all version state data. Otherwise only recent state is available. + stateRecent := uint64(core.TriesInMemory - 4) + if server.archiveMode { + stateRecent = 0 + } + send = send.add("serveRecentState", stateRecent) send = send.add("txRelay", nil) } send = send.add("flowControl/BL", server.defParams.BufLimit) send = send.add("flowControl/MRR", server.defParams.MinRecharge) - list := server.fcCostStats.getCurrentList() - send = send.add("flowControl/MRC", list) - p.fcCosts = list.decode() + + var costList RequestCostList + if server.costTracker.testCostList != nil { + costList = server.costTracker.testCostList + } else { + costList = server.costTracker.makeCostList(server.costTracker.globalFactor()) + } + send = send.add("flowControl/MRC", costList) + p.fcCosts = costList.decode(ProtocolLengths[uint(p.version)]) + p.fcParams = server.defParams + + // Add advertised checkpoint and register block height which + // client can verify the checkpoint validity. + if server.oracle != nil && server.oracle.isRunning() { + cp, height := server.oracle.stableCheckpoint() + if cp != nil { + send = send.add("checkpoint/value", cp) + send = send.add("checkpoint/registerHeight", height) + } + } } else { - //on client node + // Add some client-specific handshake fields p.announceType = announceTypeSimple - if p.isTrusted { + if p.trusted { p.announceType = announceTypeSigned } send = send.add("announceType", p.announceType) @@ -469,8 +636,10 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis if err != nil { return err } - - recv := recvList.decode() + recv, size := recvList.decode() + if p.rejectUpdate(size) { + return errResp(ErrRequestRejected, "") + } var rGenesis, rHash common.Hash var rVersion, rNetwork, rNum uint64 @@ -506,65 +675,84 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis } if server != nil { - // until we have a proper peer connectivity API, allow LES connection to other servers - /*if recv.get("serveStateSince", nil) == nil { - return errResp(ErrUselessPeer, "wanted client, got server") - }*/ if recv.get("announceType", &p.announceType) != nil { - //set default announceType on server side + // set default announceType on server side p.announceType = announceTypeSimple } p.fcClient = flowcontrol.NewClientNode(server.fcManager, server.defParams) } else { - //mark OnlyAnnounce server if "serveHeaders", "serveChainSince", "serveStateSince" or "txRelay" fields don't exist - if recv.get("serveChainSince", nil) != nil { - p.isOnlyAnnounce = true + if recv.get("serveChainSince", &p.chainSince) != nil { + p.onlyAnnounce = true } - if recv.get("serveStateSince", nil) != nil { - p.isOnlyAnnounce = true + if recv.get("serveRecentChain", &p.chainRecent) != nil { + p.chainRecent = 0 + } + if recv.get("serveStateSince", &p.stateSince) != nil { + p.onlyAnnounce = true + } + if recv.get("serveRecentState", &p.stateRecent) != nil { + p.stateRecent = 0 } if recv.get("txRelay", nil) != nil { - p.isOnlyAnnounce = true + p.onlyAnnounce = true } - if p.isOnlyAnnounce && !p.isTrusted { + if p.onlyAnnounce && !p.trusted { return errResp(ErrUselessPeer, "peer cannot serve requests") } - params := &flowcontrol.ServerParams{} - if err := recv.get("flowControl/BL", ¶ms.BufLimit); err != nil { + var sParams flowcontrol.ServerParams + if err := recv.get("flowControl/BL", &sParams.BufLimit); err != nil { return err } - if err := recv.get("flowControl/MRR", ¶ms.MinRecharge); err != nil { + if err := recv.get("flowControl/MRR", &sParams.MinRecharge); err != nil { return err } var MRC RequestCostList if err := recv.get("flowControl/MRC", &MRC); err != nil { return err } - p.fcServerParams = params - p.fcServer = flowcontrol.NewServerNode(params) - p.fcCosts = MRC.decode() - var checkList []uint64 - switch p.version { - case lpv1: - checkList = reqListV1 - case lpv2: - checkList = reqListV2 - default: - panic(nil) - } - for _, msgCode := range checkList { - if p.fcCosts[msgCode] == nil { - return errResp(ErrUselessPeer, "peer does not support message %d", msgCode) + p.fcParams = sParams + p.fcServer = flowcontrol.NewServerNode(sParams, &mclock.System{}) + p.fcCosts = MRC.decode(ProtocolLengths[uint(p.version)]) + + recv.get("checkpoint/value", &p.checkpoint) + recv.get("checkpoint/registerHeight", &p.checkpointNumber) + + if !p.onlyAnnounce { + for msgCode := range reqAvgTimeCost { + if p.fcCosts[msgCode] == nil { + return errResp(ErrUselessPeer, "peer does not support message %d", msgCode) + } } } } - p.headInfo = &announceData{Td: rTd, Hash: rHash, Number: rNum} return nil } +// updateFlowControl updates the flow control parameters belonging to the server +// node if the announced key/value set contains relevant fields +func (p *peer) updateFlowControl(update keyValueMap) { + if p.fcServer == nil { + return + } + // If any of the flow control params is nil, refuse to update. + var params flowcontrol.ServerParams + if update.get("flowControl/BL", ¶ms.BufLimit) == nil && update.get("flowControl/MRR", ¶ms.MinRecharge) == nil { + // todo can light client set a minimal acceptable flow control params? + p.fcParams = params + p.fcServer.UpdateParams(params) + } + var MRC RequestCostList + if update.get("flowControl/MRC", &MRC) == nil { + costUpdate := MRC.decode(ProtocolLengths[uint(p.version)]) + for code, cost := range costUpdate { + p.fcCosts[code] = cost + } + } +} + // String implements fmt.Stringer. func (p *peer) String() string { return fmt.Sprintf("Peer %s [%s]", p.id, diff --git a/vendor/github.com/ethereum/go-ethereum/les/protocol.go b/vendor/github.com/ethereum/go-ethereum/les/protocol.go index 0b24f5aed..5fdf32b74 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/protocol.go +++ b/vendor/github.com/ethereum/go-ethereum/les/protocol.go @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( @@ -25,8 +24,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rlp" @@ -34,19 +31,19 @@ import ( // Constants to match up protocol versions and messages const ( - lpv1 = 1 lpv2 = 2 + lpv3 = 3 ) // Supported versions of the les protocol (first is primary) var ( - ClientProtocolVersions = []uint{lpv2, lpv1} - ServerProtocolVersions = []uint{lpv2, lpv1} + ClientProtocolVersions = []uint{lpv2, lpv3} + ServerProtocolVersions = []uint{lpv2, lpv3} AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list ) // Number of implemented message corresponding to different protocol versions. -var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22} +var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24} const ( NetworkId = 1 @@ -55,7 +52,7 @@ const ( // les protocol message codes const ( - // Protocol messages belonging to LPV1 + // Protocol messages inherited from LPV1 StatusMsg = 0x00 AnnounceMsg = 0x01 GetBlockHeadersMsg = 0x02 @@ -64,14 +61,9 @@ const ( BlockBodiesMsg = 0x05 GetReceiptsMsg = 0x06 ReceiptsMsg = 0x07 - GetProofsV1Msg = 0x08 - ProofsV1Msg = 0x09 GetCodeMsg = 0x0a CodeMsg = 0x0b - SendTxMsg = 0x0c - GetHeaderProofsMsg = 0x0d - HeaderProofsMsg = 0x0e - // Protocol messages belonging to LPV2 + // Protocol messages introduced in LPV2 GetProofsV2Msg = 0x0f ProofsV2Msg = 0x10 GetHelperTrieProofsMsg = 0x11 @@ -79,8 +71,27 @@ const ( SendTxV2Msg = 0x13 GetTxStatusMsg = 0x14 TxStatusMsg = 0x15 + // Protocol messages introduced in LPV3 + StopMsg = 0x16 + ResumeMsg = 0x17 ) +type requestInfo struct { + name string + maxCount uint64 +} + +var requests = map[uint64]requestInfo{ + GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch}, + GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch}, + GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch}, + GetCodeMsg: {"GetCode", MaxCodeFetch}, + GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch}, + GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch}, + SendTxV2Msg: {"SendTxV2", MaxTxSend}, + GetTxStatusMsg: {"GetTxStatus", MaxTxStatus}, +} + type errCode int const ( @@ -138,6 +149,14 @@ type announceData struct { Update keyValueList } +// sanityCheck verifies that the values are reasonable, as a DoS protection +func (a *announceData) sanityCheck() error { + if tdlen := a.Td.BitLen(); tdlen > 100 { + return fmt.Errorf("too large block TD: bitlen %d", tdlen) + } + return nil +} + // sign adds a signature to the block announcement by the given privKey func (a *announceData) sign(privKey *ecdsa.PrivateKey) { rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td}) @@ -146,9 +165,9 @@ func (a *announceData) sign(privKey *ecdsa.PrivateKey) { } // checkSignature verifies if the block announcement has a valid signature by the given pubKey -func (a *announceData) checkSignature(id enode.ID) error { +func (a *announceData) checkSignature(id enode.ID, update keyValueMap) error { var sig []byte - if err := a.Update.decode().get("sign", &sig); err != nil { + if err := update.get("sign", &sig); err != nil { return err } rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td}) @@ -218,9 +237,3 @@ type CodeData []struct { } type proofsData [][]rlp.RawValue - -type txStatus struct { - Status core.TxStatus - Lookup *rawdb.TxLookupEntry `rlp:"nil"` - Error string -} diff --git a/vendor/github.com/ethereum/go-ethereum/les/randselect.go b/vendor/github.com/ethereum/go-ethereum/les/randselect.go index 1cc1d3d3e..8efe0c94d 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/randselect.go +++ b/vendor/github.com/ethereum/go-ethereum/les/randselect.go @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( diff --git a/vendor/github.com/ethereum/go-ethereum/les/retrieve.go b/vendor/github.com/ethereum/go-ethereum/les/retrieve.go index d77cfea74..d17a02e1a 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/retrieve.go +++ b/vendor/github.com/ethereum/go-ethereum/les/retrieve.go @@ -14,8 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package light implements on-demand retrieval capable state and chain objects -// for the Ethereum Light Client. package les import ( @@ -80,8 +78,8 @@ type sentReq struct { // after which delivered is set to true, the validity of the response is sent on the // valid channel and no more responses are accepted. type sentReqToPeer struct { - delivered bool - valid chan bool + delivered, frozen bool + event chan int } // reqPeerEvent is sent by the request-from-peer goroutine (tryRequest) to the @@ -97,6 +95,7 @@ const ( rpHardTimeout rpDeliveredValid rpDeliveredInvalid + rpNotDelivered ) // newRetrieveManager creates the retrieve manager @@ -151,7 +150,7 @@ func (rm *retrieveManager) sendReq(reqID uint64, req *distReq, val validatorFunc req.request = func(p distPeer) func() { // before actually sending the request, put an entry into the sentTo map r.lock.Lock() - r.sentTo[p] = sentReqToPeer{false, make(chan bool, 1)} + r.sentTo[p] = sentReqToPeer{delivered: false, frozen: false, event: make(chan int, 1)} r.lock.Unlock() return request(p) } @@ -175,6 +174,17 @@ func (rm *retrieveManager) deliver(peer distPeer, msg *Msg) error { return errResp(ErrUnexpectedResponse, "reqID = %v", msg.ReqID) } +// frozen is called by the LES protocol manager when a server has suspended its service and we +// should not expect an answer for the requests already sent there +func (rm *retrieveManager) frozen(peer distPeer) { + rm.lock.RLock() + defer rm.lock.RUnlock() + + for _, req := range rm.sentReqs { + req.frozen(peer) + } +} + // reqStateFn represents a state of the retrieve loop state machine type reqStateFn func() reqStateFn @@ -217,7 +227,7 @@ func (r *sentReq) stateRequesting() reqStateFn { go r.tryRequest() r.lastReqQueued = true return r.stateRequesting - case rpDeliveredInvalid: + case rpDeliveredInvalid, rpNotDelivered: // if it was the last sent request (set to nil by update) then start a new one if !r.lastReqQueued && r.lastReqSentTo == nil { go r.tryRequest() @@ -279,7 +289,7 @@ func (r *sentReq) update(ev reqPeerEvent) { r.reqSrtoCount++ case rpHardTimeout: r.reqSrtoCount-- - case rpDeliveredValid, rpDeliveredInvalid: + case rpDeliveredValid, rpDeliveredInvalid, rpNotDelivered: if ev.peer == r.lastReqSentTo { r.lastReqSentTo = nil } else { @@ -345,12 +355,13 @@ func (r *sentReq) tryRequest() { }() select { - case ok := <-s.valid: - if ok { - r.eventsCh <- reqPeerEvent{rpDeliveredValid, p} - } else { - r.eventsCh <- reqPeerEvent{rpDeliveredInvalid, p} + case event := <-s.event: + if event == rpNotDelivered { + r.lock.Lock() + delete(r.sentTo, p) + r.lock.Unlock() } + r.eventsCh <- reqPeerEvent{event, p} return case <-time.After(softRequestTimeout): srto = true @@ -358,12 +369,13 @@ func (r *sentReq) tryRequest() { } select { - case ok := <-s.valid: - if ok { - r.eventsCh <- reqPeerEvent{rpDeliveredValid, p} - } else { - r.eventsCh <- reqPeerEvent{rpDeliveredInvalid, p} + case event := <-s.event: + if event == rpNotDelivered { + r.lock.Lock() + delete(r.sentTo, p) + r.lock.Unlock() } + r.eventsCh <- reqPeerEvent{event, p} case <-time.After(hardRequestTimeout): hrto = true r.eventsCh <- reqPeerEvent{rpHardTimeout, p} @@ -379,15 +391,37 @@ func (r *sentReq) deliver(peer distPeer, msg *Msg) error { if !ok || s.delivered { return errResp(ErrUnexpectedResponse, "reqID = %v", msg.ReqID) } + if s.frozen { + return nil + } valid := r.validate(peer, msg) == nil - r.sentTo[peer] = sentReqToPeer{true, s.valid} - s.valid <- valid + r.sentTo[peer] = sentReqToPeer{delivered: true, frozen: false, event: s.event} + if valid { + s.event <- rpDeliveredValid + } else { + s.event <- rpDeliveredInvalid + } if !valid { return errResp(ErrInvalidResponse, "reqID = %v", msg.ReqID) } return nil } +// frozen sends a "not delivered" event to the peer event channel belonging to the +// given peer if the request has been sent there, causing the state machine to not +// expect an answer and potentially even send the request to the same peer again +// when canSend allows it. +func (r *sentReq) frozen(peer distPeer) { + r.lock.Lock() + defer r.lock.Unlock() + + s, ok := r.sentTo[peer] + if ok && !s.delivered && !s.frozen { + r.sentTo[peer] = sentReqToPeer{delivered: false, frozen: true, event: s.event} + s.event <- rpNotDelivered + } +} + // stop stops the retrieval process and sets an error code that will be returned // by getError func (r *sentReq) stop(err error) { diff --git a/vendor/github.com/ethereum/go-ethereum/les/server.go b/vendor/github.com/ethereum/go-ethereum/les/server.go index 2ded3c184..592858cb9 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/server.go +++ b/vendor/github.com/ethereum/go-ethereum/les/server.go @@ -14,124 +14,144 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( "crypto/ecdsa" - "encoding/binary" - "math" - "sync" + "time" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discv5" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" ) type LesServer struct { lesCommons - fcManager *flowcontrol.ClientManager // nil if our node is client only - fcCostStats *requestCostStats - defParams *flowcontrol.ServerParams - lesTopics []discv5.Topic - privateKey *ecdsa.PrivateKey - quitSync chan struct{} - onlyAnnounce bool + archiveMode bool // Flag whether the ethereum node runs in archive mode. + handler *serverHandler + lesTopics []discv5.Topic + privateKey *ecdsa.PrivateKey + + // Flow control and capacity management + fcManager *flowcontrol.ClientManager + costTracker *costTracker + defParams flowcontrol.ServerParams + servingQueue *servingQueue + clientPool *clientPool + + freeCapacity uint64 // The minimal client capacity used for free client. + threadsIdle int // Request serving threads count when system is idle. + threadsBusy int // Request serving threads count when system is busy(block insertion). } -func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) { - quitSync := make(chan struct{}) - pm, err := NewProtocolManager( - eth.BlockChain().Config(), - light.DefaultServerIndexerConfig, - false, - config.NetworkId, - eth.EventMux(), - eth.Engine(), - newPeerSet(), - eth.BlockChain(), - eth.TxPool(), - eth.ChainDb(), - nil, - nil, - nil, - quitSync, - new(sync.WaitGroup), - config.ULC) - if err != nil { - return nil, err - } - +func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) { + // Collect les protocol version information supported by local node. lesTopics := make([]discv5.Topic, len(AdvertiseProtocolVersions)) for i, pv := range AdvertiseProtocolVersions { - lesTopics[i] = lesTopic(eth.BlockChain().Genesis().Hash(), pv) + lesTopics[i] = lesTopic(e.BlockChain().Genesis().Hash(), pv) + } + // Calculate the number of threads used to service the light client + // requests based on the user-specified value. + threads := config.LightServ * 4 / 100 + if threads < 4 { + threads = 4 } - srv := &LesServer{ lesCommons: lesCommons{ + genesis: e.BlockChain().Genesis().Hash(), config: config, - chainDb: eth.ChainDb(), + chainConfig: e.BlockChain().Config(), iConfig: light.DefaultServerIndexerConfig, - chtIndexer: light.NewChtIndexer(eth.ChainDb(), nil, params.CHTFrequencyServer, params.HelperTrieProcessConfirmations), - bloomTrieIndexer: light.NewBloomTrieIndexer(eth.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency), - protocolManager: pm, + chainDb: e.ChainDb(), + peers: newPeerSet(), + chainReader: e.BlockChain(), + chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations), + bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency), + closeCh: make(chan struct{}), }, - quitSync: quitSync, + archiveMode: e.ArchiveMode(), lesTopics: lesTopics, - onlyAnnounce: config.OnlyAnnounce, + fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}), + servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100), + threadsBusy: config.LightServ/100 + 1, + threadsIdle: threads, } + srv.handler = newServerHandler(srv, e.BlockChain(), e.ChainDb(), e.TxPool(), e.Synced) + srv.costTracker, srv.freeCapacity = newCostTracker(e.ChainDb(), config) - logger := log.New() - - chtV1SectionCount, _, _ := srv.chtIndexer.Sections() // indexer still uses LES/1 4k section size for backwards server compatibility - chtV2SectionCount := chtV1SectionCount / (params.CHTFrequencyClient / params.CHTFrequencyServer) - if chtV2SectionCount != 0 { - // convert to LES/2 section - chtLastSection := chtV2SectionCount - 1 - // convert last LES/2 section index back to LES/1 index for chtIndexer.SectionHead - chtLastSectionV1 := (chtLastSection+1)*(params.CHTFrequencyClient/params.CHTFrequencyServer) - 1 - chtSectionHead := srv.chtIndexer.SectionHead(chtLastSectionV1) - chtRoot := light.GetChtRoot(pm.chainDb, chtLastSectionV1, chtSectionHead) - logger.Info("Loaded CHT", "section", chtLastSection, "head", chtSectionHead, "root", chtRoot) - } - bloomTrieSectionCount, _, _ := srv.bloomTrieIndexer.Sections() - if bloomTrieSectionCount != 0 { - bloomTrieLastSection := bloomTrieSectionCount - 1 - bloomTrieSectionHead := srv.bloomTrieIndexer.SectionHead(bloomTrieLastSection) - bloomTrieRoot := light.GetBloomTrieRoot(pm.chainDb, bloomTrieLastSection, bloomTrieSectionHead) - logger.Info("Loaded bloom trie", "section", bloomTrieLastSection, "head", bloomTrieSectionHead, "root", bloomTrieRoot) + // Set up checkpoint oracle. + oracle := config.CheckpointOracle + if oracle == nil { + oracle = params.CheckpointOracles[e.BlockChain().Genesis().Hash()] } + srv.oracle = newCheckpointOracle(oracle, srv.localCheckpoint) - srv.chtIndexer.Start(eth.BlockChain()) - pm.server = srv - - srv.defParams = &flowcontrol.ServerParams{ - BufLimit: 300000000, - MinRecharge: 50000, + // Initialize server capacity management fields. + srv.defParams = flowcontrol.ServerParams{ + BufLimit: srv.freeCapacity * bufLimitRatio, + MinRecharge: srv.freeCapacity, } - srv.fcManager = flowcontrol.NewClientManager(uint64(config.LightServ), 10, 1000000000) - srv.fcCostStats = newCostStats(eth.ChainDb()) + // LES flow control tries to more or less guarantee the possibility for the + // clients to send a certain amount of requests at any time and get a quick + // response. Most of the clients want this guarantee but don't actually need + // to send requests most of the time. Our goal is to serve as many clients as + // possible while the actually used server capacity does not exceed the limits + totalRecharge := srv.costTracker.totalRecharge() + maxCapacity := srv.freeCapacity * uint64(srv.config.LightPeers) + if totalRecharge > maxCapacity { + maxCapacity = totalRecharge + } + srv.fcManager.SetCapacityLimits(srv.freeCapacity, maxCapacity, srv.freeCapacity*2) + srv.clientPool = newClientPool(srv.chainDb, srv.freeCapacity, 10000, mclock.System{}, func(id enode.ID) { go srv.peers.Unregister(peerIdToString(id)) }) + srv.clientPool.setPriceFactors(priceFactors{0, 1, 1}, priceFactors{0, 1, 1}) + + checkpoint := srv.latestLocalCheckpoint() + if !checkpoint.Empty() { + log.Info("Loaded latest checkpoint", "section", checkpoint.SectionIndex, "head", checkpoint.SectionHead, + "chtroot", checkpoint.CHTRoot, "bloomroot", checkpoint.BloomRoot) + } + srv.chtIndexer.Start(e.BlockChain()) return srv, nil } +func (s *LesServer) APIs() []rpc.API { + return []rpc.API{ + { + Namespace: "les", + Version: "1.0", + Service: NewPrivateLightAPI(&s.lesCommons), + Public: false, + }, + } +} + func (s *LesServer) Protocols() []p2p.Protocol { - return s.makeProtocols(ServerProtocolVersions) + return s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} { + if p := s.peers.Peer(peerIdToString(id)); p != nil { + return p.Info() + } + return nil + }) } // Start starts the LES server func (s *LesServer) Start(srvr *p2p.Server) { - s.protocolManager.Start(s.config.LightPeers) + s.privateKey = srvr.PrivateKey + s.handler.start() + + s.wg.Add(1) + go s.capacityManagement() + if srvr.DiscV5 != nil { for _, topic := range s.lesTopics { topic := topic @@ -140,264 +160,101 @@ func (s *LesServer) Start(srvr *p2p.Server) { logger.Info("Starting topic registration") defer logger.Info("Terminated topic registration") - srvr.DiscV5.RegisterTopic(topic, s.quitSync) + srvr.DiscV5.RegisterTopic(topic, s.closeCh) }() } } - s.privateKey = srvr.PrivateKey - s.protocolManager.blockLoop() +} + +// Stop stops the LES service +func (s *LesServer) Stop() { + close(s.closeCh) + + // Disconnect existing sessions. + // This also closes the gate for any new registrations on the peer set. + // sessions which are already established but not added to pm.peers yet + // will exit when they try to register. + s.peers.Close() + + s.fcManager.Stop() + s.clientPool.stop() + s.costTracker.stop() + s.handler.stop() + s.servingQueue.stop() + + // Note, bloom trie indexer is closed by parent bloombits indexer. + s.chtIndexer.Close() + s.wg.Wait() + log.Info("Les server stopped") } func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) { bloomIndexer.AddChildIndexer(s.bloomTrieIndexer) } -// Stop stops the LES service -func (s *LesServer) Stop() { - s.chtIndexer.Close() - // bloom trie indexer is closed by parent bloombits indexer - s.fcCostStats.store() - s.fcManager.Stop() - go func() { - <-s.protocolManager.noMorePeers - }() - s.protocolManager.Stop() -} - -type requestCosts struct { - baseCost, reqCost uint64 -} - -type requestCostTable map[uint64]*requestCosts - -type RequestCostList []struct { - MsgCode, BaseCost, ReqCost uint64 -} - -func (list RequestCostList) decode() requestCostTable { - table := make(requestCostTable) - for _, e := range list { - table[e.MsgCode] = &requestCosts{ - baseCost: e.BaseCost, - reqCost: e.ReqCost, - } - } - return table -} - -type linReg struct { - sumX, sumY, sumXX, sumXY float64 - cnt uint64 -} - -const linRegMaxCnt = 100000 - -func (l *linReg) add(x, y float64) { - if l.cnt >= linRegMaxCnt { - sub := float64(l.cnt+1-linRegMaxCnt) / linRegMaxCnt - l.sumX -= l.sumX * sub - l.sumY -= l.sumY * sub - l.sumXX -= l.sumXX * sub - l.sumXY -= l.sumXY * sub - l.cnt = linRegMaxCnt - 1 - } - l.cnt++ - l.sumX += x - l.sumY += y - l.sumXX += x * x - l.sumXY += x * y -} - -func (l *linReg) calc() (b, m float64) { - if l.cnt == 0 { - return 0, 0 - } - cnt := float64(l.cnt) - d := cnt*l.sumXX - l.sumX*l.sumX - if d < 0.001 { - return l.sumY / cnt, 0 - } - m = (cnt*l.sumXY - l.sumX*l.sumY) / d - b = (l.sumY / cnt) - (m * l.sumX / cnt) - return b, m -} - -func (l *linReg) toBytes() []byte { - var arr [40]byte - binary.BigEndian.PutUint64(arr[0:8], math.Float64bits(l.sumX)) - binary.BigEndian.PutUint64(arr[8:16], math.Float64bits(l.sumY)) - binary.BigEndian.PutUint64(arr[16:24], math.Float64bits(l.sumXX)) - binary.BigEndian.PutUint64(arr[24:32], math.Float64bits(l.sumXY)) - binary.BigEndian.PutUint64(arr[32:40], l.cnt) - return arr[:] -} - -func linRegFromBytes(data []byte) *linReg { - if len(data) != 40 { - return nil - } - l := &linReg{} - l.sumX = math.Float64frombits(binary.BigEndian.Uint64(data[0:8])) - l.sumY = math.Float64frombits(binary.BigEndian.Uint64(data[8:16])) - l.sumXX = math.Float64frombits(binary.BigEndian.Uint64(data[16:24])) - l.sumXY = math.Float64frombits(binary.BigEndian.Uint64(data[24:32])) - l.cnt = binary.BigEndian.Uint64(data[32:40]) - return l -} - -type requestCostStats struct { - lock sync.RWMutex - db ethdb.Database - stats map[uint64]*linReg -} - -type requestCostStatsRlp []struct { - MsgCode uint64 - Data []byte -} - -var rcStatsKey = []byte("_requestCostStats") - -func newCostStats(db ethdb.Database) *requestCostStats { - stats := make(map[uint64]*linReg) - for _, code := range reqList { - stats[code] = &linReg{cnt: 100} - } - - if db != nil { - data, err := db.Get(rcStatsKey) - var statsRlp requestCostStatsRlp - if err == nil { - err = rlp.DecodeBytes(data, &statsRlp) - } - if err == nil { - for _, r := range statsRlp { - if stats[r.MsgCode] != nil { - if l := linRegFromBytes(r.Data); l != nil { - stats[r.MsgCode] = l - } - } - } - } - } - - return &requestCostStats{ - db: db, - stats: stats, - } -} - -func (s *requestCostStats) store() { - s.lock.Lock() - defer s.lock.Unlock() - - statsRlp := make(requestCostStatsRlp, len(reqList)) - for i, code := range reqList { - statsRlp[i].MsgCode = code - statsRlp[i].Data = s.stats[code].toBytes() - } - - if data, err := rlp.EncodeToBytes(statsRlp); err == nil { - s.db.Put(rcStatsKey, data) - } -} - -func (s *requestCostStats) getCurrentList() RequestCostList { - s.lock.Lock() - defer s.lock.Unlock() - - list := make(RequestCostList, len(reqList)) - for idx, code := range reqList { - b, m := s.stats[code].calc() - if m < 0 { - b += m - m = 0 - } - if b < 0 { - b = 0 - } - - list[idx].MsgCode = code - list[idx].BaseCost = uint64(b * 2) - list[idx].ReqCost = uint64(m * 2) - } - return list -} - -func (s *requestCostStats) update(msgCode, reqCnt, cost uint64) { - s.lock.Lock() - defer s.lock.Unlock() - - c, ok := s.stats[msgCode] - if !ok || reqCnt == 0 { +// SetClient sets the rpc client and starts running checkpoint contract if it is not yet watched. +func (s *LesServer) SetContractBackend(backend bind.ContractBackend) { + if s.oracle == nil { return } - c.add(float64(reqCnt), float64(cost)) + s.oracle.start(backend) } -func (pm *ProtocolManager) blockLoop() { - pm.wg.Add(1) - headCh := make(chan core.ChainHeadEvent, 10) - headSub := pm.blockchain.SubscribeChainHeadEvent(headCh) - go func() { - var lastHead *types.Header - lastBroadcastTd := common.Big0 - for { - select { - case ev := <-headCh: - peers := pm.peers.AllPeers() - if len(peers) > 0 { - header := ev.Block.Header() - hash := header.Hash() - number := header.Number.Uint64() - td := rawdb.ReadTd(pm.chainDb, hash, number) - if td != nil && td.Cmp(lastBroadcastTd) > 0 { - var reorg uint64 - if lastHead != nil { - reorg = lastHead.Number.Uint64() - rawdb.FindCommonAncestor(pm.chainDb, header, lastHead).Number.Uint64() - } - lastHead = header - lastBroadcastTd = td +// capacityManagement starts an event handler loop that updates the recharge curve of +// the client manager and adjusts the client pool's size according to the total +// capacity updates coming from the client manager +func (s *LesServer) capacityManagement() { + defer s.wg.Done() - log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg) + processCh := make(chan bool, 100) + sub := s.handler.blockchain.SubscribeBlockProcessingEvent(processCh) + defer sub.Unsubscribe() - announce := announceData{Hash: hash, Number: number, Td: td, ReorgDepth: reorg} - var ( - signed bool - signedAnnounce announceData - ) + totalRechargeCh := make(chan uint64, 100) + totalRecharge := s.costTracker.subscribeTotalRecharge(totalRechargeCh) - for _, p := range peers { - switch p.announceType { + totalCapacityCh := make(chan uint64, 100) + totalCapacity := s.fcManager.SubscribeTotalCapacity(totalCapacityCh) + s.clientPool.setLimits(s.config.LightPeers, totalCapacity) - case announceTypeSimple: - select { - case p.announceChn <- announce: - default: - pm.removePeer(p.id) - } - - case announceTypeSigned: - if !signed { - signedAnnounce = announce - signedAnnounce.sign(pm.server.privateKey) - signed = true - } - - select { - case p.announceChn <- signedAnnounce: - default: - pm.removePeer(p.id) - } - } - } - } - } - case <-pm.quitSync: - headSub.Unsubscribe() - pm.wg.Done() - return - } + var ( + busy bool + freePeers uint64 + blockProcess mclock.AbsTime + ) + updateRecharge := func() { + if busy { + s.servingQueue.setThreads(s.threadsBusy) + s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge, totalRecharge}}) + } else { + s.servingQueue.setThreads(s.threadsIdle) + s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge / 10, totalRecharge}, {totalRecharge, totalRecharge}}) } - }() + } + updateRecharge() + + for { + select { + case busy = <-processCh: + if busy { + blockProcess = mclock.Now() + } else { + blockProcessingTimer.Update(time.Duration(mclock.Now() - blockProcess)) + } + updateRecharge() + case totalRecharge = <-totalRechargeCh: + totalRechargeGauge.Update(int64(totalRecharge)) + updateRecharge() + case totalCapacity = <-totalCapacityCh: + totalCapacityGauge.Update(int64(totalCapacity)) + newFreePeers := totalCapacity / s.freeCapacity + if newFreePeers < freePeers && newFreePeers < uint64(s.config.LightPeers) { + log.Warn("Reduced free peer connections", "from", freePeers, "to", newFreePeers) + } + freePeers = newFreePeers + s.clientPool.setLimits(s.config.LightPeers, totalCapacity) + case <-s.closeCh: + return + } + } } diff --git a/vendor/github.com/ethereum/go-ethereum/les/server_handler.go b/vendor/github.com/ethereum/go-ethereum/les/server_handler.go new file mode 100644 index 000000000..16249ef1b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/server_handler.go @@ -0,0 +1,950 @@ +// Copyright 2019 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 les + +import ( + "encoding/binary" + "encoding/json" + "errors" + "sync" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +const ( + softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. + estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header + ethVersion = 63 // equivalent eth version for the downloader + + MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request + MaxBodyFetch = 32 // Amount of block bodies to be fetched per retrieval request + MaxReceiptFetch = 128 // Amount of transaction receipts to allow fetching per request + MaxCodeFetch = 64 // Amount of contract codes to allow fetching per request + MaxProofsFetch = 64 // Amount of merkle proofs to be fetched per retrieval request + MaxHelperTrieProofsFetch = 64 // Amount of helper tries to be fetched per retrieval request + MaxTxSend = 64 // Amount of transactions to be send per request + MaxTxStatus = 256 // Amount of transactions to queried per request +) + +var ( + errTooManyInvalidRequest = errors.New("too many invalid requests made") + errFullClientPool = errors.New("client pool is full") +) + +// serverHandler is responsible for serving light client and process +// all incoming light requests. +type serverHandler struct { + blockchain *core.BlockChain + chainDb ethdb.Database + txpool *core.TxPool + server *LesServer + + closeCh chan struct{} // Channel used to exit all background routines of handler. + wg sync.WaitGroup // WaitGroup used to track all background routines of handler. + synced func() bool // Callback function used to determine whether local node is synced. + + // Testing fields + addTxsSync bool +} + +func newServerHandler(server *LesServer, blockchain *core.BlockChain, chainDb ethdb.Database, txpool *core.TxPool, synced func() bool) *serverHandler { + handler := &serverHandler{ + server: server, + blockchain: blockchain, + chainDb: chainDb, + txpool: txpool, + closeCh: make(chan struct{}), + synced: synced, + } + return handler +} + +// start starts the server handler. +func (h *serverHandler) start() { + h.wg.Add(1) + go h.broadcastHeaders() +} + +// stop stops the server handler. +func (h *serverHandler) stop() { + close(h.closeCh) + h.wg.Wait() +} + +// runPeer is the p2p protocol run function for the given version. +func (h *serverHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error { + peer := newPeer(int(version), h.server.config.NetworkId, false, p, newMeteredMsgWriter(rw, int(version))) + h.wg.Add(1) + defer h.wg.Done() + return h.handle(peer) +} + +func (h *serverHandler) handle(p *peer) error { + // Reject light clients if server is not synced. + if !h.synced() { + return p2p.DiscRequested + } + p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) + + // Execute the LES handshake + var ( + head = h.blockchain.CurrentHeader() + hash = head.Hash() + number = head.Number.Uint64() + td = h.blockchain.GetTd(hash, number) + ) + if err := p.Handshake(td, hash, number, h.blockchain.Genesis().Hash(), h.server); err != nil { + p.Log().Debug("Light Ethereum handshake failed", "err", err) + return err + } + defer p.fcClient.Disconnect() + + // Disconnect the inbound peer if it's rejected by clientPool + if !h.server.clientPool.connect(p, 0) { + p.Log().Debug("Light Ethereum peer registration failed", "err", errFullClientPool) + return errFullClientPool + } + // Register the peer locally + if err := h.server.peers.Register(p); err != nil { + h.server.clientPool.disconnect(p) + p.Log().Error("Light Ethereum peer registration failed", "err", err) + return err + } + clientConnectionGauge.Update(int64(h.server.peers.Len())) + + var wg sync.WaitGroup // Wait group used to track all in-flight task routines. + + connectedAt := mclock.Now() + defer func() { + wg.Wait() // Ensure all background task routines have exited. + h.server.peers.Unregister(p.id) + h.server.clientPool.disconnect(p) + clientConnectionGauge.Update(int64(h.server.peers.Len())) + connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) + }() + + // Spawn a main loop to handle all incoming messages. + for { + select { + case err := <-p.errCh: + p.Log().Debug("Failed to send light ethereum response", "err", err) + return err + default: + } + if err := h.handleMsg(p, &wg); err != nil { + p.Log().Debug("Light Ethereum message handling failed", "err", err) + return err + } + } +} + +// handleMsg is invoked whenever an inbound message is received from a remote +// peer. The remote connection is torn down upon returning any error. +func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error { + // Read the next message from the remote peer, and ensure it's fully consumed + msg, err := p.rw.ReadMsg() + if err != nil { + return err + } + p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size) + + // Discard large message which exceeds the limitation. + if msg.Size > ProtocolMaxMsgSize { + clientErrorMeter.Mark(1) + return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) + } + defer msg.Discard() + + var ( + maxCost uint64 + task *servingTask + ) + p.responseCount++ + responseCount := p.responseCount + // accept returns an indicator whether the request can be served. + // If so, deduct the max cost from the flow control buffer. + accept := func(reqID, reqCnt, maxCnt uint64) bool { + // Short circuit if the peer is already frozen or the request is invalid. + inSizeCost := h.server.costTracker.realCost(0, msg.Size, 0) + if p.isFrozen() || reqCnt == 0 || reqCnt > maxCnt { + p.fcClient.OneTimeCost(inSizeCost) + return false + } + // Prepaid max cost units before request been serving. + maxCost = p.fcCosts.getMaxCost(msg.Code, reqCnt) + accepted, bufShort, priority := p.fcClient.AcceptRequest(reqID, responseCount, maxCost) + if !accepted { + p.freezeClient() + p.Log().Error("Request came too early", "remaining", common.PrettyDuration(time.Duration(bufShort*1000000/p.fcParams.MinRecharge))) + p.fcClient.OneTimeCost(inSizeCost) + return false + } + // Create a multi-stage task, estimate the time it takes for the task to + // execute, and cache it in the request service queue. + factor := h.server.costTracker.globalFactor() + if factor < 0.001 { + factor = 1 + p.Log().Error("Invalid global cost factor", "factor", factor) + } + maxTime := uint64(float64(maxCost) / factor) + task = h.server.servingQueue.newTask(p, maxTime, priority) + if task.start() { + return true + } + p.fcClient.RequestProcessed(reqID, responseCount, maxCost, inSizeCost) + return false + } + // sendResponse sends back the response and updates the flow control statistic. + sendResponse := func(reqID, amount uint64, reply *reply, servingTime uint64) { + p.responseLock.Lock() + defer p.responseLock.Unlock() + + // Short circuit if the client is already frozen. + if p.isFrozen() { + realCost := h.server.costTracker.realCost(servingTime, msg.Size, 0) + p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) + return + } + // Positive correction buffer value with real cost. + var replySize uint32 + if reply != nil { + replySize = reply.size() + } + var realCost uint64 + if h.server.costTracker.testing { + realCost = maxCost // Assign a fake cost for testing purpose + } else { + realCost = h.server.costTracker.realCost(servingTime, msg.Size, replySize) + } + bv := p.fcClient.RequestProcessed(reqID, responseCount, maxCost, realCost) + if amount != 0 { + // Feed cost tracker request serving statistic. + h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) + // Reduce priority "balance" for the specific peer. + h.server.clientPool.requestCost(p, realCost) + } + if reply != nil { + p.queueSend(func() { + if err := reply.send(bv); err != nil { + select { + case p.errCh <- err: + default: + } + } + }) + } + } + switch msg.Code { + case GetBlockHeadersMsg: + p.Log().Trace("Received block header request") + if metrics.EnabledExpensive { + miscInHeaderPacketsMeter.Mark(1) + miscInHeaderTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeHeaderTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Query getBlockHeadersData + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "%v: %v", msg, err) + } + query := req.Query + if accept(req.ReqID, query.Amount, MaxHeaderFetch) { + wg.Add(1) + go func() { + defer wg.Done() + hashMode := query.Origin.Hash != (common.Hash{}) + first := true + maxNonCanonical := uint64(100) + + // Gather headers until the fetch or network limits is reached + var ( + bytes common.StorageSize + headers []*types.Header + unknown bool + ) + for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit { + if !first && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Retrieve the next header satisfying the query + var origin *types.Header + if hashMode { + if first { + origin = h.blockchain.GetHeaderByHash(query.Origin.Hash) + if origin != nil { + query.Origin.Number = origin.Number.Uint64() + } + } else { + origin = h.blockchain.GetHeader(query.Origin.Hash, query.Origin.Number) + } + } else { + origin = h.blockchain.GetHeaderByNumber(query.Origin.Number) + } + if origin == nil { + atomic.AddUint32(&p.invalidCount, 1) + break + } + headers = append(headers, origin) + bytes += estHeaderRlpSize + + // Advance to the next header of the query + switch { + case hashMode && query.Reverse: + // Hash based traversal towards the genesis block + ancestor := query.Skip + 1 + if ancestor == 0 { + unknown = true + } else { + query.Origin.Hash, query.Origin.Number = h.blockchain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) + unknown = query.Origin.Hash == common.Hash{} + } + case hashMode && !query.Reverse: + // Hash based traversal towards the leaf block + var ( + current = origin.Number.Uint64() + next = current + query.Skip + 1 + ) + if next <= current { + infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ") + p.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) + unknown = true + } else { + if header := h.blockchain.GetHeaderByNumber(next); header != nil { + nextHash := header.Hash() + expOldHash, _ := h.blockchain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) + if expOldHash == query.Origin.Hash { + query.Origin.Hash, query.Origin.Number = nextHash, next + } else { + unknown = true + } + } else { + unknown = true + } + } + case query.Reverse: + // Number based traversal towards the genesis block + if query.Origin.Number >= query.Skip+1 { + query.Origin.Number -= query.Skip + 1 + } else { + unknown = true + } + + case !query.Reverse: + // Number based traversal towards the leaf block + query.Origin.Number += query.Skip + 1 + } + first = false + } + reply := p.ReplyBlockHeaders(req.ReqID, headers) + sendResponse(req.ReqID, query.Amount, p.ReplyBlockHeaders(req.ReqID, headers), task.done()) + if metrics.EnabledExpensive { + miscOutHeaderPacketsMeter.Mark(1) + miscOutHeaderTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetBlockBodiesMsg: + p.Log().Trace("Received block bodies request") + if metrics.EnabledExpensive { + miscInBodyPacketsMeter.Mark(1) + miscInBodyTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeBodyTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + bodies []rlp.RawValue + ) + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if bytes >= softResponseLimit { + break + } + body := h.blockchain.GetBodyRLP(hash) + if body == nil { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + bodies = append(bodies, body) + bytes += len(body) + } + reply := p.ReplyBlockBodiesRLP(req.ReqID, bodies) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutBodyPacketsMeter.Mark(1) + miscOutBodyTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetCodeMsg: + p.Log().Trace("Received code request") + if metrics.EnabledExpensive { + miscInCodePacketsMeter.Mark(1) + miscInCodeTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeCodeTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []CodeReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + data [][]byte + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Look up the root hash belonging to the request + header := h.blockchain.GetHeaderByHash(request.BHash) + if header == nil { + p.Log().Warn("Failed to retrieve associate header for code", "hash", request.BHash) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Refuse to search stale state data in the database since looking for + // a non-exist key is kind of expensive. + local := h.blockchain.CurrentHeader().Number.Uint64() + if !h.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { + p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + triedb := h.blockchain.StateCache().TrieDB() + + account, err := h.getAccount(triedb, header.Root, common.BytesToHash(request.AccKey)) + if err != nil { + p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + code, err := triedb.Node(common.BytesToHash(account.CodeHash)) + if err != nil { + p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err) + continue + } + // Accumulate the code and abort if enough data was retrieved + data = append(data, code) + if bytes += len(code); bytes >= softResponseLimit { + break + } + } + reply := p.ReplyCode(req.ReqID, data) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutCodePacketsMeter.Mark(1) + miscOutCodeTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetReceiptsMsg: + p.Log().Trace("Received receipts request") + if metrics.EnabledExpensive { + miscInReceiptPacketsMeter.Mark(1) + miscInReceiptTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeReceiptTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + var ( + bytes int + receipts []rlp.RawValue + ) + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { + wg.Add(1) + go func() { + defer wg.Done() + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if bytes >= softResponseLimit { + break + } + // Retrieve the requested block's receipts, skipping if unknown to us + results := h.blockchain.GetReceiptsByHash(hash) + if results == nil { + if header := h.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + } + // If known, encode and queue for response packet + if encoded, err := rlp.EncodeToBytes(results); err != nil { + log.Error("Failed to encode receipt", "err", err) + } else { + receipts = append(receipts, encoded) + bytes += len(encoded) + } + } + reply := p.ReplyReceiptsRLP(req.ReqID, receipts) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutReceiptPacketsMeter.Mark(1) + miscOutReceiptTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetProofsV2Msg: + p.Log().Trace("Received les/2 proofs request") + if metrics.EnabledExpensive { + miscInTrieProofPacketsMeter.Mark(1) + miscInTrieProofTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTrieProofTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []ProofReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + // Gather state data until the fetch or network limits is reached + var ( + lastBHash common.Hash + root common.Hash + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { + wg.Add(1) + go func() { + defer wg.Done() + nodes := light.NewNodeSet() + + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + // Look up the root hash belonging to the request + var ( + header *types.Header + trie state.Trie + ) + if request.BHash != lastBHash { + root, lastBHash = common.Hash{}, request.BHash + + if header = h.blockchain.GetHeaderByHash(request.BHash); header == nil { + p.Log().Warn("Failed to retrieve header for proof", "hash", request.BHash) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Refuse to search stale state data in the database since looking for + // a non-exist key is kind of expensive. + local := h.blockchain.CurrentHeader().Number.Uint64() + if !h.server.archiveMode && header.Number.Uint64()+core.TriesInMemory <= local { + p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + root = header.Root + } + // If a header lookup failed (non existent), ignore subsequent requests for the same header + if root == (common.Hash{}) { + atomic.AddUint32(&p.invalidCount, 1) + continue + } + // Open the account or storage trie for the request + statedb := h.blockchain.StateCache() + + switch len(request.AccKey) { + case 0: + // No account key specified, open an account trie + trie, err = statedb.OpenTrie(root) + if trie == nil || err != nil { + p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err) + continue + } + default: + // Account key specified, open a storage trie + account, err := h.getAccount(statedb.TrieDB(), root, common.BytesToHash(request.AccKey)) + if err != nil { + p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "err", err) + atomic.AddUint32(&p.invalidCount, 1) + continue + } + trie, err = statedb.OpenStorageTrie(common.BytesToHash(request.AccKey), account.Root) + if trie == nil || err != nil { + p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(request.AccKey), "root", account.Root, "err", err) + continue + } + } + // Prove the user's request from the account or stroage trie + if err := trie.Prove(request.Key, request.FromLevel, nodes); err != nil { + p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err) + continue + } + if nodes.DataSize() >= softResponseLimit { + break + } + } + reply := p.ReplyProofsV2(req.ReqID, nodes.NodeList()) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTrieProofPacketsMeter.Mark(1) + miscOutTrieProofTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetHelperTrieProofsMsg: + p.Log().Trace("Received helper trie proof request") + if metrics.EnabledExpensive { + miscInHelperTriePacketsMeter.Mark(1) + miscInHelperTrieTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeHelperTrieTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Reqs []HelperTrieReq + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + // Gather state data until the fetch or network limits is reached + var ( + auxBytes int + auxData [][]byte + ) + reqCnt := len(req.Reqs) + if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { + wg.Add(1) + go func() { + defer wg.Done() + var ( + lastIdx uint64 + lastType uint + root common.Hash + auxTrie *trie.Trie + ) + nodes := light.NewNodeSet() + for i, request := range req.Reqs { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + if auxTrie == nil || request.Type != lastType || request.TrieIdx != lastIdx { + auxTrie, lastType, lastIdx = nil, request.Type, request.TrieIdx + + var prefix string + if root, prefix = h.getHelperTrie(request.Type, request.TrieIdx); root != (common.Hash{}) { + auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(h.chainDb, prefix))) + } + } + if request.AuxReq == auxRoot { + var data []byte + if root != (common.Hash{}) { + data = root[:] + } + auxData = append(auxData, data) + auxBytes += len(data) + } else { + if auxTrie != nil { + auxTrie.Prove(request.Key, request.FromLevel, nodes) + } + if request.AuxReq != 0 { + data := h.getAuxiliaryHeaders(request) + auxData = append(auxData, data) + auxBytes += len(data) + } + } + if nodes.DataSize()+auxBytes >= softResponseLimit { + break + } + } + reply := p.ReplyHelperTrieProofs(req.ReqID, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData}) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutHelperTriePacketsMeter.Mark(1) + miscOutHelperTrieTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case SendTxV2Msg: + p.Log().Trace("Received new transactions") + if metrics.EnabledExpensive { + miscInTxsPacketsMeter.Mark(1) + miscInTxsTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTxTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Txs []*types.Transaction + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + reqCnt := len(req.Txs) + if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { + wg.Add(1) + go func() { + defer wg.Done() + stats := make([]light.TxStatus, len(req.Txs)) + for i, tx := range req.Txs { + if i != 0 && !task.waitOrStop() { + return + } + hash := tx.Hash() + stats[i] = h.txStatus(hash) + if stats[i].Status == core.TxStatusUnknown { + addFn := h.txpool.AddRemotes + // Add txs synchronously for testing purpose + if h.addTxsSync { + addFn = h.txpool.AddRemotesSync + } + if errs := addFn([]*types.Transaction{tx}); errs[0] != nil { + stats[i].Error = errs[0].Error() + continue + } + stats[i] = h.txStatus(hash) + } + } + reply := p.ReplyTxStatus(req.ReqID, stats) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTxsPacketsMeter.Mark(1) + miscOutTxsTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + case GetTxStatusMsg: + p.Log().Trace("Received transaction status query request") + if metrics.EnabledExpensive { + miscInTxStatusPacketsMeter.Mark(1) + miscInTxStatusTrafficMeter.Mark(int64(msg.Size)) + defer func(start time.Time) { miscServingTimeTxStatusTimer.UpdateSince(start) }(time.Now()) + } + var req struct { + ReqID uint64 + Hashes []common.Hash + } + if err := msg.Decode(&req); err != nil { + clientErrorMeter.Mark(1) + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + reqCnt := len(req.Hashes) + if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { + wg.Add(1) + go func() { + defer wg.Done() + stats := make([]light.TxStatus, len(req.Hashes)) + for i, hash := range req.Hashes { + if i != 0 && !task.waitOrStop() { + sendResponse(req.ReqID, 0, nil, task.servingTime) + return + } + stats[i] = h.txStatus(hash) + } + reply := p.ReplyTxStatus(req.ReqID, stats) + sendResponse(req.ReqID, uint64(reqCnt), reply, task.done()) + if metrics.EnabledExpensive { + miscOutTxStatusPacketsMeter.Mark(1) + miscOutTxStatusTrafficMeter.Mark(int64(reply.size())) + } + }() + } + + default: + p.Log().Trace("Received invalid message", "code", msg.Code) + clientErrorMeter.Mark(1) + return errResp(ErrInvalidMsgCode, "%v", msg.Code) + } + // If the client has made too much invalid request(e.g. request a non-exist data), + // reject them to prevent SPAM attack. + if atomic.LoadUint32(&p.invalidCount) > maxRequestErrors { + clientErrorMeter.Mark(1) + return errTooManyInvalidRequest + } + return nil +} + +// getAccount retrieves an account from the state based on root. +func (h *serverHandler) getAccount(triedb *trie.Database, root, hash common.Hash) (state.Account, error) { + trie, err := trie.New(root, triedb) + if err != nil { + return state.Account{}, err + } + blob, err := trie.TryGet(hash[:]) + if err != nil { + return state.Account{}, err + } + var account state.Account + if err = rlp.DecodeBytes(blob, &account); err != nil { + return state.Account{}, err + } + return account, nil +} + +// getHelperTrie returns the post-processed trie root for the given trie ID and section index +func (h *serverHandler) getHelperTrie(typ uint, index uint64) (common.Hash, string) { + switch typ { + case htCanonical: + sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.ChtSize-1) + return light.GetChtRoot(h.chainDb, index, sectionHead), light.ChtTablePrefix + case htBloomBits: + sectionHead := rawdb.ReadCanonicalHash(h.chainDb, (index+1)*h.server.iConfig.BloomTrieSize-1) + return light.GetBloomTrieRoot(h.chainDb, index, sectionHead), light.BloomTrieTablePrefix + } + return common.Hash{}, "" +} + +// getAuxiliaryHeaders returns requested auxiliary headers for the CHT request. +func (h *serverHandler) getAuxiliaryHeaders(req HelperTrieReq) []byte { + if req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8 { + blockNum := binary.BigEndian.Uint64(req.Key) + hash := rawdb.ReadCanonicalHash(h.chainDb, blockNum) + return rawdb.ReadHeaderRLP(h.chainDb, hash, blockNum) + } + return nil +} + +// txStatus returns the status of a specified transaction. +func (h *serverHandler) txStatus(hash common.Hash) light.TxStatus { + var stat light.TxStatus + // Looking the transaction in txpool first. + stat.Status = h.txpool.Status([]common.Hash{hash})[0] + + // If the transaction is unknown to the pool, try looking it up locally. + if stat.Status == core.TxStatusUnknown { + lookup := h.blockchain.GetTransactionLookup(hash) + if lookup != nil { + stat.Status = core.TxStatusIncluded + stat.Lookup = lookup + } + } + return stat +} + +// broadcastHeaders broadcasts new block information to all connected light +// clients. According to the agreement between client and server, server should +// only broadcast new announcement if the total difficulty is higher than the +// last one. Besides server will add the signature if client requires. +func (h *serverHandler) broadcastHeaders() { + defer h.wg.Done() + + headCh := make(chan core.ChainHeadEvent, 10) + headSub := h.blockchain.SubscribeChainHeadEvent(headCh) + defer headSub.Unsubscribe() + + var ( + lastHead *types.Header + lastTd = common.Big0 + ) + for { + select { + case ev := <-headCh: + peers := h.server.peers.AllPeers() + if len(peers) == 0 { + continue + } + header := ev.Block.Header() + hash, number := header.Hash(), header.Number.Uint64() + td := h.blockchain.GetTd(hash, number) + if td == nil || td.Cmp(lastTd) <= 0 { + continue + } + var reorg uint64 + if lastHead != nil { + reorg = lastHead.Number.Uint64() - rawdb.FindCommonAncestor(h.chainDb, header, lastHead).Number.Uint64() + } + lastHead, lastTd = header, td + + log.Debug("Announcing block to peers", "number", number, "hash", hash, "td", td, "reorg", reorg) + var ( + signed bool + signedAnnounce announceData + ) + announce := announceData{Hash: hash, Number: number, Td: td, ReorgDepth: reorg} + for _, p := range peers { + p := p + switch p.announceType { + case announceTypeSimple: + p.queueSend(func() { p.SendAnnounce(announce) }) + case announceTypeSigned: + if !signed { + signedAnnounce = announce + signedAnnounce.sign(h.server.privateKey) + signed = true + } + p.queueSend(func() { p.SendAnnounce(signedAnnounce) }) + } + } + case <-h.closeCh: + return + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/serverpool.go b/vendor/github.com/ethereum/go-ethereum/les/serverpool.go index e1feb965a..37621dc63 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/serverpool.go +++ b/vendor/github.com/ethereum/go-ethereum/les/serverpool.go @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package les implements the Light Ethereum Subprotocol. package les import ( @@ -116,8 +115,6 @@ type serverPool struct { db ethdb.Database dbKey []byte server *p2p.Server - quit chan struct{} - wg *sync.WaitGroup connWg sync.WaitGroup topic discv5.Topic @@ -126,26 +123,27 @@ type serverPool struct { discNodes chan *enode.Node discLookups chan bool - trustedNodes []string + trustedNodes map[enode.ID]*enode.Node entries map[enode.ID]*poolEntry timeout, enableRetry chan *poolEntry adjustStats chan poolStatAdjust - knownQueue, newQueue, trustedQueue poolEntryQueue - knownSelect, newSelect *weightedRandomSelect - knownSelected, newSelected int - fastDiscover bool - connCh chan *connReq - disconnCh chan *disconnReq - registerCh chan *registerReq + knownQueue, newQueue poolEntryQueue + knownSelect, newSelect *weightedRandomSelect + knownSelected, newSelected int + fastDiscover bool + connCh chan *connReq + disconnCh chan *disconnReq + registerCh chan *registerReq + + closeCh chan struct{} + wg sync.WaitGroup } // newServerPool creates a new serverPool instance -func newServerPool(db ethdb.Database, quit chan struct{}, wg *sync.WaitGroup, trustedNodes []string) *serverPool { +func newServerPool(db ethdb.Database, ulcServers []string) *serverPool { pool := &serverPool{ db: db, - quit: quit, - wg: wg, entries: make(map[enode.ID]*poolEntry), timeout: make(chan *poolEntry, 1), adjustStats: make(chan poolStatAdjust, 100), @@ -153,13 +151,13 @@ func newServerPool(db ethdb.Database, quit chan struct{}, wg *sync.WaitGroup, tr connCh: make(chan *connReq), disconnCh: make(chan *disconnReq), registerCh: make(chan *registerReq), + closeCh: make(chan struct{}), knownSelect: newWeightedRandomSelect(), newSelect: newWeightedRandomSelect(), fastDiscover: true, - trustedNodes: trustedNodes, + trustedNodes: parseTrustedNodes(ulcServers), } - pool.trustedQueue = newPoolEntryQueue(maxKnownEntries, nil) pool.knownQueue = newPoolEntryQueue(maxKnownEntries, pool.removeEntry) pool.newQueue = newPoolEntryQueue(maxNewEntries, pool.removeEntry) return pool @@ -169,7 +167,6 @@ func (pool *serverPool) start(server *p2p.Server, topic discv5.Topic) { pool.server = server pool.topic = topic pool.dbKey = append([]byte("serverPool/"), []byte(topic)...) - pool.wg.Add(1) pool.loadNodes() pool.connectToTrustedNodes() @@ -180,9 +177,15 @@ func (pool *serverPool) start(server *p2p.Server, topic discv5.Topic) { go pool.discoverNodes() } pool.checkDial() + pool.wg.Add(1) go pool.eventLoop() } +func (pool *serverPool) stop() { + close(pool.closeCh) + pool.wg.Wait() +} + // discoverNodes wraps SearchTopic, converting result nodes to enode.Node. func (pool *serverPool) discoverNodes() { ch := make(chan *discv5.Node) @@ -209,7 +212,7 @@ func (pool *serverPool) connect(p *peer, node *enode.Node) *poolEntry { req := &connReq{p: p, node: node, result: make(chan *poolEntry, 1)} select { case pool.connCh <- req: - case <-pool.quit: + case <-pool.closeCh: return nil } return <-req.result @@ -221,7 +224,7 @@ func (pool *serverPool) registered(entry *poolEntry) { req := ®isterReq{entry: entry, done: make(chan struct{})} select { case pool.registerCh <- req: - case <-pool.quit: + case <-pool.closeCh: return } <-req.done @@ -233,7 +236,7 @@ func (pool *serverPool) registered(entry *poolEntry) { func (pool *serverPool) disconnect(entry *poolEntry) { stopped := false select { - case <-pool.quit: + case <-pool.closeCh: stopped = true default: } @@ -280,6 +283,7 @@ func (pool *serverPool) adjustResponseTime(entry *poolEntry, time time.Duration, // eventLoop handles pool events and mutex locking for all internal functions func (pool *serverPool) eventLoop() { + defer pool.wg.Done() lookupCnt := 0 var convTime mclock.AbsTime if pool.discSetPeriod != nil { @@ -341,8 +345,10 @@ func (pool *serverPool) eventLoop() { } case node := <-pool.discNodes: - entry := pool.findOrNewNode(node) - pool.updateCheckDial(entry) + if pool.trustedNodes[node.ID()] == nil { + entry := pool.findOrNewNode(node) + pool.updateCheckDial(entry) + } case conv := <-pool.discLookups: if conv { @@ -359,31 +365,39 @@ func (pool *serverPool) eventLoop() { } case req := <-pool.connCh: - // Handle peer connection requests. - entry := pool.entries[req.p.ID()] - if entry == nil { - entry = pool.findOrNewNode(req.node) + if pool.trustedNodes[req.p.ID()] != nil { + // ignore trusted nodes + req.result <- &poolEntry{trusted: true} + } else { + // Handle peer connection requests. + entry := pool.entries[req.p.ID()] + if entry == nil { + entry = pool.findOrNewNode(req.node) + } + if entry.state == psConnected || entry.state == psRegistered { + req.result <- nil + continue + } + pool.connWg.Add(1) + entry.peer = req.p + entry.state = psConnected + addr := &poolEntryAddress{ + ip: req.node.IP(), + port: uint16(req.node.TCP()), + lastSeen: mclock.Now(), + } + entry.lastConnected = addr + entry.addr = make(map[string]*poolEntryAddress) + entry.addr[addr.strKey()] = addr + entry.addrSelect = *newWeightedRandomSelect() + entry.addrSelect.update(addr) + req.result <- entry } - if entry.state == psConnected || entry.state == psRegistered { - req.result <- nil - continue - } - pool.connWg.Add(1) - entry.peer = req.p - entry.state = psConnected - addr := &poolEntryAddress{ - ip: req.node.IP(), - port: uint16(req.node.TCP()), - lastSeen: mclock.Now(), - } - entry.lastConnected = addr - entry.addr = make(map[string]*poolEntryAddress) - entry.addr[addr.strKey()] = addr - entry.addrSelect = *newWeightedRandomSelect() - entry.addrSelect.update(addr) - req.result <- entry case req := <-pool.registerCh: + if req.entry.trusted { + continue + } // Handle peer registration requests. entry := req.entry entry.state = psRegistered @@ -397,10 +411,13 @@ func (pool *serverPool) eventLoop() { close(req.done) case req := <-pool.disconnCh: + if req.entry.trusted { + continue + } // Handle peer disconnection requests. disconnect(req, req.stopped) - case <-pool.quit: + case <-pool.closeCh: if pool.discSetPeriod != nil { close(pool.discSetPeriod) } @@ -416,7 +433,6 @@ func (pool *serverPool) eventLoop() { disconnect(req, true) } pool.saveNodes() - pool.wg.Done() return } } @@ -449,7 +465,7 @@ func (pool *serverPool) findOrNewNode(node *enode.Node) *poolEntry { } addr.lastSeen = now entry.addrSelect.update(addr) - if !entry.known || !entry.trusted { + if !entry.known { pool.newQueue.setLatest(entry) } return entry @@ -474,35 +490,38 @@ func (pool *serverPool) loadNodes() { "response", fmt.Sprintf("%v/%v", time.Duration(e.responseStats.avg), e.responseStats.weight), "timeout", fmt.Sprintf("%v/%v", e.timeoutStats.avg, e.timeoutStats.weight)) pool.entries[e.node.ID()] = e - pool.knownQueue.setLatest(e) - pool.knownSelect.update((*knownEntry)(e)) - } -} - -func (pool *serverPool) connectToTrustedNodes() { - //connect to trusted nodes - if len(pool.trustedNodes) > 0 { - for _, trusted := range pool.parseTrustedServers() { - e := pool.findOrNewNode(trusted) - e.trusted = true - e.dialed = &poolEntryAddress{ip: trusted.IP(), port: uint16(trusted.TCP())} - pool.entries[e.node.ID()] = e - pool.trustedQueue.setLatest(e) + if pool.trustedNodes[e.node.ID()] == nil { + pool.knownQueue.setLatest(e) + pool.knownSelect.update((*knownEntry)(e)) } } } -// parseTrustedServers returns valid and parsed by discovery enodes. -func (pool *serverPool) parseTrustedServers() []*enode.Node { - nodes := make([]*enode.Node, 0, len(pool.trustedNodes)) - +// connectToTrustedNodes adds trusted server nodes as static trusted peers. +// +// Note: trusted nodes are not handled by the server pool logic, they are not +// added to either the known or new selection pools. They are connected/reconnected +// by p2p.Server whenever possible. +func (pool *serverPool) connectToTrustedNodes() { + //connect to trusted nodes for _, node := range pool.trustedNodes { - node, err := enode.ParseV4(node) + pool.server.AddTrustedPeer(node) + pool.server.AddPeer(node) + log.Debug("Added trusted node", "id", node.ID().String()) + } +} + +// parseTrustedNodes returns valid and parsed enodes +func parseTrustedNodes(trustedNodes []string) map[enode.ID]*enode.Node { + nodes := make(map[enode.ID]*enode.Node) + + for _, node := range trustedNodes { + node, err := enode.Parse(enode.ValidSchemes, node) if err != nil { log.Warn("Trusted node URL invalid", "enode", node, "err", err) continue } - nodes = append(nodes, node) + nodes[node.ID()] = node } return nodes } @@ -541,10 +560,10 @@ func (pool *serverPool) setRetryDial(entry *poolEntry) { entry.delayedRetry = true go func() { select { - case <-pool.quit: + case <-pool.closeCh: case <-time.After(delay): select { - case <-pool.quit: + case <-pool.closeCh: case pool.enableRetry <- entry: } } @@ -562,10 +581,6 @@ func (pool *serverPool) updateCheckDial(entry *poolEntry) { // checkDial checks if new dials can/should be made. It tries to select servers both // based on good statistics and recent discovery. func (pool *serverPool) checkDial() { - for _, e := range pool.trustedQueue.queue { - pool.dial(e, false) - } - fillWithKnownSelects := !pool.fastDiscover for pool.knownSelected < targetKnownSelect { entry := pool.knownSelect.choose() @@ -602,31 +617,22 @@ func (pool *serverPool) dial(entry *poolEntry, knownSelected bool) { return } entry.state = psDialed - - if !entry.trusted { - entry.knownSelected = knownSelected - if knownSelected { - pool.knownSelected++ - } else { - pool.newSelected++ - } - addr := entry.addrSelect.choose().(*poolEntryAddress) - entry.dialed = addr + entry.knownSelected = knownSelected + if knownSelected { + pool.knownSelected++ + } else { + pool.newSelected++ } - - state := "known" - if entry.trusted { - state = "trusted" - } - log.Debug("Dialing new peer", "lesaddr", entry.node.ID().String()+"@"+entry.dialed.strKey(), "set", len(entry.addr), state, knownSelected) - + addr := entry.addrSelect.choose().(*poolEntryAddress) + log.Debug("Dialing new peer", "lesaddr", entry.node.ID().String()+"@"+addr.strKey(), "set", len(entry.addr), "known", knownSelected) + entry.dialed = addr go func() { pool.server.AddPeer(entry.node) select { - case <-pool.quit: + case <-pool.closeCh: case <-time.After(dialTimeout): select { - case <-pool.quit: + case <-pool.closeCh: case pool.timeout <- entry: } } @@ -667,15 +673,14 @@ type poolEntry struct { lastConnected, dialed *poolEntryAddress addrSelect weightedRandomSelect - lastDiscovered mclock.AbsTime - known, knownSelected bool - trusted bool - connectStats, delayStats poolStats - responseStats, timeoutStats poolStats - state int - regTime mclock.AbsTime - queueIdx int - removed bool + lastDiscovered mclock.AbsTime + known, knownSelected, trusted bool + connectStats, delayStats poolStats + responseStats, timeoutStats poolStats + state int + regTime mclock.AbsTime + queueIdx int + removed bool delayedRetry bool shortRetry int @@ -889,7 +894,7 @@ func (q *poolEntryQueue) setLatest(entry *poolEntry) { if q.queue[entry.queueIdx] == entry { delete(q.queue, entry.queueIdx) } else { - if len(q.queue) == q.maxCnt && q.removeFromPool != nil { + if len(q.queue) == q.maxCnt { e := q.fetchOldest() q.remove(e) q.removeFromPool(e) diff --git a/vendor/github.com/ethereum/go-ethereum/les/servingqueue.go b/vendor/github.com/ethereum/go-ethereum/les/servingqueue.go new file mode 100644 index 000000000..8842cf9e9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/servingqueue.go @@ -0,0 +1,378 @@ +// Copyright 2019 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 les + +import ( + "sort" + "sync" + "sync/atomic" + + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/common/prque" +) + +// servingQueue allows running tasks in a limited number of threads and puts the +// waiting tasks in a priority queue +type servingQueue struct { + recentTime, queuedTime, servingTimeDiff uint64 + burstLimit, burstDropLimit uint64 + burstDecRate float64 + lastUpdate mclock.AbsTime + + queueAddCh, queueBestCh chan *servingTask + stopThreadCh, quit chan struct{} + setThreadsCh chan int + + wg sync.WaitGroup + threadCount int // number of currently running threads + queue *prque.Prque // priority queue for waiting or suspended tasks + best *servingTask // the highest priority task (not included in the queue) + suspendBias int64 // priority bias against suspending an already running task +} + +// servingTask represents a request serving task. Tasks can be implemented to +// run in multiple steps, allowing the serving queue to suspend execution between +// steps if higher priority tasks are entered. The creator of the task should +// set the following fields: +// +// - priority: greater value means higher priority; values can wrap around the int64 range +// - run: execute a single step; return true if finished +// - after: executed after run finishes or returns an error, receives the total serving time +type servingTask struct { + sq *servingQueue + servingTime, timeAdded, maxTime, expTime uint64 + peer *peer + priority int64 + biasAdded bool + token runToken + tokenCh chan runToken +} + +// runToken received by servingTask.start allows the task to run. Closing the +// channel by servingTask.stop signals the thread controller to allow a new task +// to start running. +type runToken chan struct{} + +// start blocks until the task can start and returns true if it is allowed to run. +// Returning false means that the task should be cancelled. +func (t *servingTask) start() bool { + if t.peer.isFrozen() { + return false + } + t.tokenCh = make(chan runToken, 1) + select { + case t.sq.queueAddCh <- t: + case <-t.sq.quit: + return false + } + select { + case t.token = <-t.tokenCh: + case <-t.sq.quit: + return false + } + if t.token == nil { + return false + } + t.servingTime -= uint64(mclock.Now()) + return true +} + +// done signals the thread controller about the task being finished and returns +// the total serving time of the task in nanoseconds. +func (t *servingTask) done() uint64 { + t.servingTime += uint64(mclock.Now()) + close(t.token) + diff := t.servingTime - t.timeAdded + t.timeAdded = t.servingTime + if t.expTime > diff { + t.expTime -= diff + atomic.AddUint64(&t.sq.servingTimeDiff, t.expTime) + } else { + t.expTime = 0 + } + return t.servingTime +} + +// waitOrStop can be called during the execution of the task. It blocks if there +// is a higher priority task waiting (a bias is applied in favor of the currently +// running task). Returning true means that the execution can be resumed. False +// means the task should be cancelled. +func (t *servingTask) waitOrStop() bool { + t.done() + if !t.biasAdded { + t.priority += t.sq.suspendBias + t.biasAdded = true + } + return t.start() +} + +// newServingQueue returns a new servingQueue +func newServingQueue(suspendBias int64, utilTarget float64) *servingQueue { + sq := &servingQueue{ + queue: prque.New(nil), + suspendBias: suspendBias, + queueAddCh: make(chan *servingTask, 100), + queueBestCh: make(chan *servingTask), + stopThreadCh: make(chan struct{}), + quit: make(chan struct{}), + setThreadsCh: make(chan int, 10), + burstLimit: uint64(utilTarget * bufLimitRatio * 1200000), + burstDropLimit: uint64(utilTarget * bufLimitRatio * 1000000), + burstDecRate: utilTarget, + lastUpdate: mclock.Now(), + } + sq.wg.Add(2) + go sq.queueLoop() + go sq.threadCountLoop() + return sq +} + +// newTask creates a new task with the given priority +func (sq *servingQueue) newTask(peer *peer, maxTime uint64, priority int64) *servingTask { + return &servingTask{ + sq: sq, + peer: peer, + maxTime: maxTime, + expTime: maxTime, + priority: priority, + } +} + +// threadController is started in multiple goroutines and controls the execution +// of tasks. The number of active thread controllers equals the allowed number of +// concurrently running threads. It tries to fetch the highest priority queued +// task first. If there are no queued tasks waiting then it can directly catch +// run tokens from the token channel and allow the corresponding tasks to run +// without entering the priority queue. +func (sq *servingQueue) threadController() { + for { + token := make(runToken) + select { + case best := <-sq.queueBestCh: + best.tokenCh <- token + case <-sq.stopThreadCh: + sq.wg.Done() + return + case <-sq.quit: + sq.wg.Done() + return + } + <-token + select { + case <-sq.stopThreadCh: + sq.wg.Done() + return + case <-sq.quit: + sq.wg.Done() + return + default: + } + } +} + +type ( + // peerTasks lists the tasks received from a given peer when selecting peers to freeze + peerTasks struct { + peer *peer + list []*servingTask + sumTime uint64 + priority float64 + } + // peerList is a sortable list of peerTasks + peerList []*peerTasks +) + +func (l peerList) Len() int { + return len(l) +} + +func (l peerList) Less(i, j int) bool { + return l[i].priority < l[j].priority +} + +func (l peerList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +// freezePeers selects the peers with the worst priority queued tasks and freezes +// them until burstTime goes under burstDropLimit or all peers are frozen +func (sq *servingQueue) freezePeers() { + peerMap := make(map[*peer]*peerTasks) + var peerList peerList + if sq.best != nil { + sq.queue.Push(sq.best, sq.best.priority) + } + sq.best = nil + for sq.queue.Size() > 0 { + task := sq.queue.PopItem().(*servingTask) + tasks := peerMap[task.peer] + if tasks == nil { + bufValue, bufLimit := task.peer.fcClient.BufferStatus() + if bufLimit < 1 { + bufLimit = 1 + } + tasks = &peerTasks{ + peer: task.peer, + priority: float64(bufValue) / float64(bufLimit), // lower value comes first + } + peerMap[task.peer] = tasks + peerList = append(peerList, tasks) + } + tasks.list = append(tasks.list, task) + tasks.sumTime += task.expTime + } + sort.Sort(peerList) + drop := true + for _, tasks := range peerList { + if drop { + tasks.peer.freezeClient() + tasks.peer.fcClient.Freeze() + sq.queuedTime -= tasks.sumTime + sqQueuedGauge.Update(int64(sq.queuedTime)) + clientFreezeMeter.Mark(1) + drop = sq.recentTime+sq.queuedTime > sq.burstDropLimit + for _, task := range tasks.list { + task.tokenCh <- nil + } + } else { + for _, task := range tasks.list { + sq.queue.Push(task, task.priority) + } + } + } + if sq.queue.Size() > 0 { + sq.best = sq.queue.PopItem().(*servingTask) + } +} + +// updateRecentTime recalculates the recent serving time value +func (sq *servingQueue) updateRecentTime() { + subTime := atomic.SwapUint64(&sq.servingTimeDiff, 0) + now := mclock.Now() + dt := now - sq.lastUpdate + sq.lastUpdate = now + if dt > 0 { + subTime += uint64(float64(dt) * sq.burstDecRate) + } + if sq.recentTime > subTime { + sq.recentTime -= subTime + } else { + sq.recentTime = 0 + } +} + +// addTask inserts a task into the priority queue +func (sq *servingQueue) addTask(task *servingTask) { + if sq.best == nil { + sq.best = task + } else if task.priority > sq.best.priority { + sq.queue.Push(sq.best, sq.best.priority) + sq.best = task + } else { + sq.queue.Push(task, task.priority) + } + sq.updateRecentTime() + sq.queuedTime += task.expTime + sqServedGauge.Update(int64(sq.recentTime)) + sqQueuedGauge.Update(int64(sq.queuedTime)) + if sq.recentTime+sq.queuedTime > sq.burstLimit { + sq.freezePeers() + } +} + +// queueLoop is an event loop running in a goroutine. It receives tasks from queueAddCh +// and always tries to send the highest priority task to queueBestCh. Successfully sent +// tasks are removed from the queue. +func (sq *servingQueue) queueLoop() { + for { + if sq.best != nil { + expTime := sq.best.expTime + select { + case task := <-sq.queueAddCh: + sq.addTask(task) + case sq.queueBestCh <- sq.best: + sq.updateRecentTime() + sq.queuedTime -= expTime + sq.recentTime += expTime + sqServedGauge.Update(int64(sq.recentTime)) + sqQueuedGauge.Update(int64(sq.queuedTime)) + if sq.queue.Size() == 0 { + sq.best = nil + } else { + sq.best, _ = sq.queue.PopItem().(*servingTask) + } + case <-sq.quit: + sq.wg.Done() + return + } + } else { + select { + case task := <-sq.queueAddCh: + sq.addTask(task) + case <-sq.quit: + sq.wg.Done() + return + } + } + } +} + +// threadCountLoop is an event loop running in a goroutine. It adjusts the number +// of active thread controller goroutines. +func (sq *servingQueue) threadCountLoop() { + var threadCountTarget int + for { + for threadCountTarget > sq.threadCount { + sq.wg.Add(1) + go sq.threadController() + sq.threadCount++ + } + if threadCountTarget < sq.threadCount { + select { + case threadCountTarget = <-sq.setThreadsCh: + case sq.stopThreadCh <- struct{}{}: + sq.threadCount-- + case <-sq.quit: + sq.wg.Done() + return + } + } else { + select { + case threadCountTarget = <-sq.setThreadsCh: + case <-sq.quit: + sq.wg.Done() + return + } + } + } +} + +// setThreads sets the allowed processing thread count, suspending tasks as soon as +// possible if necessary. +func (sq *servingQueue) setThreads(threadCount int) { + select { + case sq.setThreadsCh <- threadCount: + case <-sq.quit: + return + } +} + +// stop stops task processing as soon as possible and shuts down the serving queue. +func (sq *servingQueue) stop() { + close(sq.quit) + sq.wg.Wait() +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/sync.go b/vendor/github.com/ethereum/go-ethereum/les/sync.go index 1ac645585..693394464 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/les/sync.go @@ -18,62 +18,166 @@ package les import ( "context" + "errors" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/log" ) -// syncer is responsible for periodically synchronising with the network, both -// downloading hashes and blocks as well as handling the announcement handler. -func (pm *ProtocolManager) syncer() { - // Start and ensure cleanup of sync mechanisms - //pm.fetcher.Start() - //defer pm.fetcher.Stop() - defer pm.downloader.Terminate() +var errInvalidCheckpoint = errors.New("invalid advertised checkpoint") - // Wait for different events to fire synchronisation operations - //forceSync := time.Tick(forceSyncCycle) - for { - select { - case <-pm.newPeerCh: - /* // Make sure we have peers to select from, then sync - if pm.peers.Len() < minDesiredPeerCount { - break - } - go pm.synchronise(pm.peers.BestPeer()) - */ - /*case <-forceSync: - // Force a sync even if not enough peers are present - go pm.synchronise(pm.peers.BestPeer()) - */ - case <-pm.noMorePeers: - return - } +const ( + // lightSync starts syncing from the current highest block. + // If the chain is empty, syncing the entire header chain. + lightSync = iota + + // legacyCheckpointSync starts syncing from a hardcoded checkpoint. + legacyCheckpointSync + + // checkpointSync starts syncing from a checkpoint signed by trusted + // signer or hardcoded checkpoint for compatibility. + checkpointSync +) + +// validateCheckpoint verifies the advertised checkpoint by peer is valid or not. +// +// Each network has several hard-coded checkpoint signer addresses. Only the +// checkpoint issued by the specified signer is considered valid. +// +// In addition to the checkpoint registered in the registrar contract, there are +// several legacy hardcoded checkpoints in our codebase. These checkpoints are +// also considered as valid. +func (h *clientHandler) validateCheckpoint(peer *peer) error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + // Fetch the block header corresponding to the checkpoint registration. + cp := peer.checkpoint + header, err := light.GetUntrustedHeaderByNumber(ctx, h.backend.odr, peer.checkpointNumber, peer.id) + if err != nil { + return err } + // Fetch block logs associated with the block header. + logs, err := light.GetUntrustedBlockLogs(ctx, h.backend.odr, header) + if err != nil { + return err + } + events := h.backend.oracle.contract.LookupCheckpointEvents(logs, cp.SectionIndex, cp.Hash()) + if len(events) == 0 { + return errInvalidCheckpoint + } + var ( + index = events[0].Index + hash = events[0].CheckpointHash + signatures [][]byte + ) + for _, event := range events { + signatures = append(signatures, append(event.R[:], append(event.S[:], event.V)...)) + } + valid, signers := h.backend.oracle.verifySigners(index, hash, signatures) + if !valid { + return errInvalidCheckpoint + } + log.Warn("Verified advertised checkpoint", "peer", peer.id, "signers", len(signers)) + return nil } -func (pm *ProtocolManager) needToSync(peerHead blockInfo) bool { - head := pm.blockchain.CurrentHeader() - currentTd := rawdb.ReadTd(pm.chainDb, head.Hash(), head.Number.Uint64()) - return currentTd != nil && peerHead.Td.Cmp(currentTd) > 0 -} - -// synchronise tries to sync up our local block chain with a remote peer. -func (pm *ProtocolManager) synchronise(peer *peer) { - // Short circuit if no peers are available +// synchronise tries to sync up our local chain with a remote peer. +func (h *clientHandler) synchronise(peer *peer) { + // Short circuit if the peer is nil. if peer == nil { return } - // Make sure the peer's TD is higher than our own. - if !pm.needToSync(peer.headBlockInfo()) { + latest := h.backend.blockchain.CurrentHeader() + currentTd := rawdb.ReadTd(h.backend.chainDb, latest.Hash(), latest.Number.Uint64()) + if currentTd != nil && peer.headBlockInfo().Td.Cmp(currentTd) < 0 { return } + // Recap the checkpoint. + // + // The light client may be connected to several different versions of the server. + // (1) Old version server which can not provide stable checkpoint in the handshake packet. + // => Use hardcoded checkpoint or empty checkpoint + // (2) New version server but simple checkpoint syncing is not enabled(e.g. mainnet, new testnet or private network) + // => Use hardcoded checkpoint or empty checkpoint + // (3) New version server but the provided stable checkpoint is even lower than the hardcoded one. + // => Use hardcoded checkpoint + // (4) New version server with valid and higher stable checkpoint + // => Use provided checkpoint + var checkpoint = &peer.checkpoint + var hardcoded bool + if h.checkpoint != nil && h.checkpoint.SectionIndex >= peer.checkpoint.SectionIndex { + checkpoint = h.checkpoint // Use the hardcoded one. + hardcoded = true + } + // Determine whether we should run checkpoint syncing or normal light syncing. + // + // Here has four situations that we will disable the checkpoint syncing: + // + // 1. The checkpoint is empty + // 2. The latest head block of the local chain is above the checkpoint. + // 3. The checkpoint is hardcoded(recap with local hardcoded checkpoint) + // 4. For some networks the checkpoint syncing is not activated. + mode := checkpointSync + switch { + case checkpoint.Empty(): + mode = lightSync + log.Debug("Disable checkpoint syncing", "reason", "empty checkpoint") + case latest.Number.Uint64() >= (checkpoint.SectionIndex+1)*h.backend.iConfig.ChtSize-1: + mode = lightSync + log.Debug("Disable checkpoint syncing", "reason", "local chain beyond the checkpoint") + case hardcoded: + mode = legacyCheckpointSync + log.Debug("Disable checkpoint syncing", "reason", "checkpoint is hardcoded") + case h.backend.oracle == nil || !h.backend.oracle.isRunning(): + mode = legacyCheckpointSync + log.Debug("Disable checkpoint syncing", "reason", "checkpoint syncing is not activated") + } + // Notify testing framework if syncing has completed(for testing purpose). + defer func() { + if h.backend.oracle != nil && h.backend.oracle.syncDoneHook != nil { + h.backend.oracle.syncDoneHook() + } + }() + start := time.Now() + if mode == checkpointSync || mode == legacyCheckpointSync { + // Validate the advertised checkpoint + if mode == legacyCheckpointSync { + checkpoint = h.checkpoint + } else if mode == checkpointSync { + if err := h.validateCheckpoint(peer); err != nil { + log.Debug("Failed to validate checkpoint", "reason", err) + h.removePeer(peer.id) + return + } + h.backend.blockchain.AddTrustedCheckpoint(checkpoint) + } + log.Debug("Checkpoint syncing start", "peer", peer.id, "checkpoint", checkpoint.SectionIndex) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - pm.blockchain.(*light.LightChain).SyncCht(ctx) - pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync) + // Fetch the start point block header. + // + // For the ethash consensus engine, the start header is the block header + // of the checkpoint. + // + // For the clique consensus engine, the start header is the block header + // of the latest epoch covered by checkpoint. + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + if !checkpoint.Empty() && !h.backend.blockchain.SyncCheckpoint(ctx, checkpoint) { + log.Debug("Sync checkpoint failed") + h.removePeer(peer.id) + return + } + } + // Fetch the remaining block headers based on the current chain header. + if err := h.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync); err != nil { + log.Debug("Synchronise failed", "reason", err) + return + } + log.Debug("Synchronise finished", "elapsed", common.PrettyDuration(time.Since(start))) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/test_helper.go b/vendor/github.com/ethereum/go-ethereum/les/test_helper.go new file mode 100644 index 000000000..79cf323d6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/les/test_helper.go @@ -0,0 +1,558 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// This file contains some shares testing functionality, common to multiple +// different files and modules being tested. + +package les + +import ( + "context" + "crypto/rand" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/les/flowcontrol" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/params" +) + +var ( + bankKey, _ = crypto.GenerateKey() + bankAddr = crypto.PubkeyToAddress(bankKey.PublicKey) + bankFunds = big.NewInt(1000000000000000000) + + userKey1, _ = crypto.GenerateKey() + userKey2, _ = crypto.GenerateKey() + userAddr1 = crypto.PubkeyToAddress(userKey1.PublicKey) + userAddr2 = crypto.PubkeyToAddress(userKey2.PublicKey) + + testContractAddr common.Address + testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") + testContractCodeDeployed = testContractCode[16:] + testContractDeployed = uint64(2) + + testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029") + + // Checkpoint registrar relative + registrarAddr common.Address + signerKey, _ = crypto.GenerateKey() + signerAddr = crypto.PubkeyToAddress(signerKey.PublicKey) +) + +var ( + // The block frequency for creating checkpoint(only used in test) + sectionSize = big.NewInt(512) + + // The number of confirmations needed to generate a checkpoint(only used in test). + processConfirms = big.NewInt(4) + + // The token bucket buffer limit for testing purpose. + testBufLimit = uint64(1000000) + + // The buffer recharging speed for testing purpose. + testBufRecharge = uint64(1000) +) + +/* +contract test { + + uint256[100] data; + + function Put(uint256 addr, uint256 value) { + data[addr] = value; + } + + function Get(uint256 addr) constant returns (uint256 value) { + return data[addr]; + } +} +*/ + +// prepare pre-commits specified number customized blocks into chain. +func prepare(n int, backend *backends.SimulatedBackend) { + var ( + ctx = context.Background() + signer = types.HomesteadSigner{} + ) + for i := 0; i < n; i++ { + switch i { + case 0: + // deploy checkpoint contract + registrarAddr, _, _, _ = contract.DeployCheckpointOracle(bind.NewKeyedTransactor(bankKey), backend, []common.Address{signerAddr}, sectionSize, processConfirms, big.NewInt(1)) + // bankUser transfers some ether to user1 + nonce, _ := backend.PendingNonceAt(ctx, bankAddr) + tx, _ := types.SignTx(types.NewTransaction(nonce, userAddr1, big.NewInt(10000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx) + case 1: + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + userNonce1, _ := backend.PendingNonceAt(ctx, userAddr1) + + // bankUser transfers more ether to user1 + tx1, _ := types.SignTx(types.NewTransaction(bankNonce, userAddr1, big.NewInt(1000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx1) + + // user1 relays ether to user2 + tx2, _ := types.SignTx(types.NewTransaction(userNonce1, userAddr2, big.NewInt(1000), params.TxGas, nil, nil), signer, userKey1) + backend.SendTransaction(ctx, tx2) + + // user1 deploys a test contract + tx3, _ := types.SignTx(types.NewContractCreation(userNonce1+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, userKey1) + backend.SendTransaction(ctx, tx3) + testContractAddr = crypto.CreateAddress(userAddr1, userNonce1+1) + + // user1 deploys a event contract + tx4, _ := types.SignTx(types.NewContractCreation(userNonce1+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, userKey1) + backend.SendTransaction(ctx, tx4) + case 2: + // bankUser transfer some ether to signer + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + tx1, _ := types.SignTx(types.NewTransaction(bankNonce, signerAddr, big.NewInt(1000000000), params.TxGas, nil, nil), signer, bankKey) + backend.SendTransaction(ctx, tx1) + + // invoke test contract + data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") + tx2, _ := types.SignTx(types.NewTransaction(bankNonce+1, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) + backend.SendTransaction(ctx, tx2) + case 3: + // invoke test contract + bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) + data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") + tx, _ := types.SignTx(types.NewTransaction(bankNonce, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) + backend.SendTransaction(ctx, tx) + } + backend.Commit() + } +} + +// testIndexers creates a set of indexers with specified params for testing purpose. +func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.IndexerConfig) []*core.ChainIndexer { + var indexers [3]*core.ChainIndexer + indexers[0] = light.NewChtIndexer(db, odr, config.ChtSize, config.ChtConfirms) + indexers[1] = eth.NewBloomIndexer(db, config.BloomSize, config.BloomConfirms) + indexers[2] = light.NewBloomTrieIndexer(db, odr, config.BloomSize, config.BloomTrieSize) + // make bloomTrieIndexer as a child indexer of bloom indexer. + indexers[1].AddChildIndexer(indexers[2]) + return indexers[:] +} + +func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, ulcServers []string, ulcFraction int) *clientHandler { + var ( + evmux = new(event.TypeMux) + engine = ethash.NewFaker() + gspec = core.Genesis{ + Config: params.AllEthashProtocolChanges, + Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, + GasLimit: 100000000, + } + oracle *checkpointOracle + ) + genesis := gspec.MustCommit(db) + chain, _ := light.NewLightChain(odr, gspec.Config, engine, nil) + if indexers != nil { + checkpointConfig := ¶ms.CheckpointOracleConfig{ + Address: crypto.CreateAddress(bankAddr, 0), + Signers: []common.Address{signerAddr}, + Threshold: 1, + } + getLocal := func(index uint64) params.TrustedCheckpoint { + chtIndexer := indexers[0] + sectionHead := chtIndexer.SectionHead(index) + return params.TrustedCheckpoint{ + SectionIndex: index, + SectionHead: sectionHead, + CHTRoot: light.GetChtRoot(db, index, sectionHead), + BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), + } + } + oracle = newCheckpointOracle(checkpointConfig, getLocal) + } + client := &LightEthereum{ + lesCommons: lesCommons{ + genesis: genesis.Hash(), + config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, + chainConfig: params.AllEthashProtocolChanges, + iConfig: light.TestClientIndexerConfig, + chainDb: db, + oracle: oracle, + chainReader: chain, + peers: peers, + closeCh: make(chan struct{}), + }, + reqDist: odr.retriever.dist, + retriever: odr.retriever, + odr: odr, + engine: engine, + blockchain: chain, + eventMux: evmux, + } + client.handler = newClientHandler(ulcServers, ulcFraction, nil, client) + + if client.oracle != nil { + client.oracle.start(backend) + } + return client.handler +} + +func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) { + var ( + gspec = core.Genesis{ + Config: params.AllEthashProtocolChanges, + Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, + GasLimit: 100000000, + } + oracle *checkpointOracle + ) + genesis := gspec.MustCommit(db) + + // create a simulation backend and pre-commit several customized block to the database. + simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000) + prepare(blocks, simulation) + + txpoolConfig := core.DefaultTxPoolConfig + txpoolConfig.Journal = "" + txpool := core.NewTxPool(txpoolConfig, gspec.Config, simulation.Blockchain()) + if indexers != nil { + checkpointConfig := ¶ms.CheckpointOracleConfig{ + Address: crypto.CreateAddress(bankAddr, 0), + Signers: []common.Address{signerAddr}, + Threshold: 1, + } + getLocal := func(index uint64) params.TrustedCheckpoint { + chtIndexer := indexers[0] + sectionHead := chtIndexer.SectionHead(index) + return params.TrustedCheckpoint{ + SectionIndex: index, + SectionHead: sectionHead, + CHTRoot: light.GetChtRoot(db, index, sectionHead), + BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), + } + } + oracle = newCheckpointOracle(checkpointConfig, getLocal) + } + server := &LesServer{ + lesCommons: lesCommons{ + genesis: genesis.Hash(), + config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, + chainConfig: params.AllEthashProtocolChanges, + iConfig: light.TestServerIndexerConfig, + chainDb: db, + chainReader: simulation.Blockchain(), + oracle: oracle, + peers: peers, + closeCh: make(chan struct{}), + }, + servingQueue: newServingQueue(int64(time.Millisecond*10), 1), + defParams: flowcontrol.ServerParams{ + BufLimit: testBufLimit, + MinRecharge: testBufRecharge, + }, + fcManager: flowcontrol.NewClientManager(nil, clock), + } + server.costTracker, server.freeCapacity = newCostTracker(db, server.config) + server.costTracker.testCostList = testCostList(0) // Disable flow control mechanism. + server.clientPool = newClientPool(db, 1, 10000, clock, nil) + server.clientPool.setLimits(10000, 10000) // Assign enough capacity for clientpool + server.handler = newServerHandler(server, simulation.Blockchain(), db, txpool, func() bool { return true }) + if server.oracle != nil { + server.oracle.start(simulation) + } + server.servingQueue.setThreads(4) + server.handler.start() + return server.handler, simulation +} + +// testPeer is a simulated peer to allow testing direct network calls. +type testPeer struct { + peer *peer + + net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging + app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side +} + +// newTestPeer creates a new peer registered at the given protocol manager. +func newTestPeer(t *testing.T, name string, version int, handler *serverHandler, shake bool, testCost uint64) (*testPeer, <-chan error) { + // Create a message pipe to communicate through + app, net := p2p.MsgPipe() + + // Generate a random id and create the peer + var id enode.ID + rand.Read(id[:]) + peer := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net) + + // Start the peer on a new thread + errCh := make(chan error, 1) + go func() { + select { + case <-handler.closeCh: + errCh <- p2p.DiscQuitting + case errCh <- handler.handle(peer): + } + }() + tp := &testPeer{ + app: app, + net: net, + peer: peer, + } + // Execute any implicitly requested handshakes and return + if shake { + // Customize the cost table if required. + if testCost != 0 { + handler.server.costTracker.testCostList = testCostList(testCost) + } + var ( + genesis = handler.blockchain.Genesis() + head = handler.blockchain.CurrentHeader() + td = handler.blockchain.GetTd(head.Hash(), head.Number.Uint64()) + ) + tp.handshake(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash(), testCostList(testCost)) + } + return tp, errCh +} + +// close terminates the local side of the peer, notifying the remote protocol +// manager of termination. +func (p *testPeer) close() { + p.app.Close() +} + +func newTestPeerPair(name string, version int, server *serverHandler, client *clientHandler) (*testPeer, <-chan error, *testPeer, <-chan error) { + // Create a message pipe to communicate through + app, net := p2p.MsgPipe() + + // Generate a random id and create the peer + var id enode.ID + rand.Read(id[:]) + + peer1 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), net) + peer2 := newPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), app) + + // Start the peer on a new thread + errc1 := make(chan error, 1) + errc2 := make(chan error, 1) + go func() { + select { + case <-server.closeCh: + errc1 <- p2p.DiscQuitting + case errc1 <- server.handle(peer1): + } + }() + go func() { + select { + case <-client.closeCh: + errc1 <- p2p.DiscQuitting + case errc1 <- client.handle(peer2): + } + }() + return &testPeer{peer: peer1, net: net, app: app}, errc1, &testPeer{peer: peer2, net: app, app: net}, errc2 +} + +// handshake simulates a trivial handshake that expects the same state from the +// remote side as we are simulating locally. +func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, costList RequestCostList) { + var expList keyValueList + expList = expList.add("protocolVersion", uint64(p.peer.version)) + expList = expList.add("networkId", uint64(NetworkId)) + expList = expList.add("headTd", td) + expList = expList.add("headHash", head) + expList = expList.add("headNum", headNum) + expList = expList.add("genesisHash", genesis) + sendList := make(keyValueList, len(expList)) + copy(sendList, expList) + expList = expList.add("serveHeaders", nil) + expList = expList.add("serveChainSince", uint64(0)) + expList = expList.add("serveStateSince", uint64(0)) + expList = expList.add("serveRecentState", uint64(core.TriesInMemory-4)) + expList = expList.add("txRelay", nil) + expList = expList.add("flowControl/BL", testBufLimit) + expList = expList.add("flowControl/MRR", testBufRecharge) + expList = expList.add("flowControl/MRC", costList) + + if err := p2p.ExpectMsg(p.app, StatusMsg, expList); err != nil { + t.Fatalf("status recv: %v", err) + } + if err := p2p.Send(p.app, StatusMsg, sendList); err != nil { + t.Fatalf("status send: %v", err) + } + p.peer.fcParams = flowcontrol.ServerParams{ + BufLimit: testBufLimit, + MinRecharge: testBufRecharge, + } +} + +type indexerCallback func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer) + +// testClient represents a client for testing with necessary auxiliary fields. +type testClient struct { + clock mclock.Clock + db ethdb.Database + peer *testPeer + handler *clientHandler + + chtIndexer *core.ChainIndexer + bloomIndexer *core.ChainIndexer + bloomTrieIndexer *core.ChainIndexer +} + +// testServer represents a server for testing with necessary auxiliary fields. +type testServer struct { + clock mclock.Clock + backend *backends.SimulatedBackend + db ethdb.Database + peer *testPeer + handler *serverHandler + + chtIndexer *core.ChainIndexer + bloomIndexer *core.ChainIndexer + bloomTrieIndexer *core.ChainIndexer +} + +func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, simClock bool, newPeer bool, testCost uint64) (*testServer, func()) { + db := rawdb.NewMemoryDatabase() + indexers := testIndexers(db, nil, light.TestServerIndexerConfig) + + var clock mclock.Clock = &mclock.System{} + if simClock { + clock = &mclock.Simulated{} + } + handler, b := newTestServerHandler(blocks, indexers, db, newPeerSet(), clock) + + var peer *testPeer + if newPeer { + peer, _ = newTestPeer(t, "peer", protocol, handler, true, testCost) + } + + cIndexer, bIndexer, btIndexer := indexers[0], indexers[1], indexers[2] + cIndexer.Start(handler.blockchain) + bIndexer.Start(handler.blockchain) + + // Wait until indexers generate enough index data. + if callback != nil { + callback(cIndexer, bIndexer, btIndexer) + } + server := &testServer{ + clock: clock, + backend: b, + db: db, + peer: peer, + handler: handler, + chtIndexer: cIndexer, + bloomIndexer: bIndexer, + bloomTrieIndexer: btIndexer, + } + teardown := func() { + if newPeer { + peer.close() + b.Close() + } + cIndexer.Close() + bIndexer.Close() + } + return server, teardown +} + +func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) { + sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase() + speers, cPeers := newPeerSet(), newPeerSet() + + var clock mclock.Clock = &mclock.System{} + if simClock { + clock = &mclock.Simulated{} + } + dist := newRequestDistributor(cPeers, clock) + rm := newRetrieveManager(cPeers, dist, nil) + odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm) + + sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig) + cIndexers := testIndexers(cdb, odr, light.TestClientIndexerConfig) + + scIndexer, sbIndexer, sbtIndexer := sindexers[0], sindexers[1], sindexers[2] + ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2] + odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer) + + server, b := newTestServerHandler(blocks, sindexers, sdb, speers, clock) + client := newTestClientHandler(b, odr, cIndexers, cdb, cPeers, ulcServers, ulcFraction) + + scIndexer.Start(server.blockchain) + sbIndexer.Start(server.blockchain) + ccIndexer.Start(client.backend.blockchain) + cbIndexer.Start(client.backend.blockchain) + + if callback != nil { + callback(scIndexer, sbIndexer, sbtIndexer) + } + var ( + speer, cpeer *testPeer + err1, err2 <-chan error + ) + if connect { + cpeer, err1, speer, err2 = newTestPeerPair("peer", protocol, server, client) + select { + case <-time.After(time.Millisecond * 100): + case err := <-err1: + t.Fatalf("peer 1 handshake error: %v", err) + case err := <-err2: + t.Fatalf("peer 2 handshake error: %v", err) + } + } + s := &testServer{ + clock: clock, + backend: b, + db: sdb, + peer: cpeer, + handler: server, + chtIndexer: scIndexer, + bloomIndexer: sbIndexer, + bloomTrieIndexer: sbtIndexer, + } + c := &testClient{ + clock: clock, + db: cdb, + peer: speer, + handler: client, + chtIndexer: ccIndexer, + bloomIndexer: cbIndexer, + bloomTrieIndexer: cbtIndexer, + } + teardown := func() { + if connect { + speer.close() + cpeer.close() + } + ccIndexer.Close() + cbIndexer.Close() + scIndexer.Close() + sbIndexer.Close() + b.Close() + } + return s, c, teardown +} diff --git a/vendor/github.com/ethereum/go-ethereum/les/txrelay.go b/vendor/github.com/ethereum/go-ethereum/les/txrelay.go index ec275ed89..49195161b 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/txrelay.go +++ b/vendor/github.com/ethereum/go-ethereum/les/txrelay.go @@ -17,6 +17,7 @@ package les import ( + "context" "sync" "github.com/ethereum/go-ethereum/common" @@ -29,36 +30,42 @@ type ltrInfo struct { sentTo map[*peer]struct{} } -type LesTxRelay struct { +type lesTxRelay struct { txSent map[common.Hash]*ltrInfo txPending map[common.Hash]struct{} ps *peerSet peerList []*peer peerStartPos int lock sync.RWMutex + stop chan struct{} - reqDist *requestDistributor + retriever *retrieveManager } -func NewLesTxRelay(ps *peerSet, reqDist *requestDistributor) *LesTxRelay { - r := &LesTxRelay{ +func newLesTxRelay(ps *peerSet, retriever *retrieveManager) *lesTxRelay { + r := &lesTxRelay{ txSent: make(map[common.Hash]*ltrInfo), txPending: make(map[common.Hash]struct{}), ps: ps, - reqDist: reqDist, + retriever: retriever, + stop: make(chan struct{}), } ps.notify(r) return r } -func (self *LesTxRelay) registerPeer(p *peer) { +func (self *lesTxRelay) Stop() { + close(self.stop) +} + +func (self *lesTxRelay) registerPeer(p *peer) { self.lock.Lock() defer self.lock.Unlock() self.peerList = self.ps.AllPeers() } -func (self *LesTxRelay) unregisterPeer(p *peer) { +func (self *lesTxRelay) unregisterPeer(p *peer) { self.lock.Lock() defer self.lock.Unlock() @@ -67,7 +74,7 @@ func (self *LesTxRelay) unregisterPeer(p *peer) { // send sends a list of transactions to at most a given number of peers at // once, never resending any particular transaction to the same peer twice -func (self *LesTxRelay) send(txs types.Transactions, count int) { +func (self *lesTxRelay) send(txs types.Transactions, count int) { sendTo := make(map[*peer]types.Transactions) self.peerStartPos++ // rotate the starting position of the peer list @@ -123,30 +130,27 @@ func (self *LesTxRelay) send(txs types.Transactions, count int) { return peer.GetTxRelayCost(len(ll), len(enc)) }, canSend: func(dp distPeer) bool { - if !dp.(*peer).isOnlyAnnounce { - return dp.(*peer) == pp - } - return false + return !dp.(*peer).onlyAnnounce && dp.(*peer) == pp }, request: func(dp distPeer) func() { peer := dp.(*peer) cost := peer.GetTxRelayCost(len(ll), len(enc)) - peer.fcServer.QueueRequest(reqID, cost) + peer.fcServer.QueuedRequest(reqID, cost) return func() { peer.SendTxs(reqID, cost, enc) } }, } - self.reqDist.queue(rq) + go self.retriever.retrieve(context.Background(), reqID, rq, func(p distPeer, msg *Msg) error { return nil }, self.stop) } } -func (self *LesTxRelay) Send(txs types.Transactions) { +func (self *lesTxRelay) Send(txs types.Transactions) { self.lock.Lock() defer self.lock.Unlock() self.send(txs, 3) } -func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { +func (self *lesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { self.lock.Lock() defer self.lock.Unlock() @@ -169,7 +173,7 @@ func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback } } -func (self *LesTxRelay) Discard(hashes []common.Hash) { +func (self *lesTxRelay) Discard(hashes []common.Hash) { self.lock.Lock() defer self.lock.Unlock() diff --git a/vendor/github.com/ethereum/go-ethereum/les/ulc.go b/vendor/github.com/ethereum/go-ethereum/les/ulc.go index d9f7dc76c..b97217e79 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/ulc.go +++ b/vendor/github.com/ethereum/go-ethereum/les/ulc.go @@ -1,39 +1,54 @@ +// Copyright 2019 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 les import ( - "fmt" + "errors" - "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" ) type ulc struct { - trustedKeys map[string]struct{} - minTrustedFraction int + keys map[string]bool + fraction int } -func newULC(ulcConfig *eth.ULCConfig) *ulc { - if ulcConfig == nil { - return nil - } - - m := make(map[string]struct{}, len(ulcConfig.TrustedServers)) - for _, id := range ulcConfig.TrustedServers { - node, err := enode.ParseV4(id) +// newULC creates and returns an ultra light client instance. +func newULC(servers []string, fraction int) (*ulc, error) { + keys := make(map[string]bool) + for _, id := range servers { + node, err := enode.Parse(enode.ValidSchemes, id) if err != nil { - fmt.Println("node:", id, " err:", err) + log.Warn("Failed to parse trusted server", "id", id, "err", err) continue } - m[node.ID().String()] = struct{}{} + keys[node.ID().String()] = true } - - return &ulc{m, ulcConfig.MinTrustedFraction} + if len(keys) == 0 { + return nil, errors.New("no trusted servers") + } + return &ulc{ + keys: keys, + fraction: fraction, + }, nil } -func (u *ulc) isTrusted(p enode.ID) bool { - if u.trustedKeys == nil { - return false - } - _, ok := u.trustedKeys[p.String()] - return ok +// trusted return an indicator that whether the specified peer is trusted. +func (u *ulc) trusted(p enode.ID) bool { + return u.keys[p.String()] } diff --git a/vendor/github.com/ethereum/go-ethereum/light/lightchain.go b/vendor/github.com/ethereum/go-ethereum/light/lightchain.go index 31f32d219..9529c2e1b 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/lightchain.go +++ b/vendor/github.com/ethereum/go-ethereum/light/lightchain.go @@ -14,6 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +// Package light implements on-demand retrieval capable state and chain objects +// for the Ethereum Light Client. package light import ( @@ -35,7 +37,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" - "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru" ) var ( @@ -50,6 +52,7 @@ type LightChain struct { hc *core.HeaderChain indexerConfig *IndexerConfig chainDb ethdb.Database + engine consensus.Engine odr OdrBackend chainFeed event.Feed chainSideFeed event.Feed @@ -57,28 +60,24 @@ type LightChain struct { scope event.SubscriptionScope genesisBlock *types.Block - mu sync.RWMutex - chainmu sync.RWMutex - bodyCache *lru.Cache // Cache for the most recent block bodies bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format blockCache *lru.Cache // Cache for the most recent entire blocks + chainmu sync.RWMutex // protects header inserts quit chan struct{} - running int32 // running must be called automically - // procInterrupt must be atomically called - procInterrupt int32 // interrupt signaler for block processing - wg sync.WaitGroup + wg sync.WaitGroup - engine consensus.Engine - - disableCheckFreq bool + // Atomic boolean switches: + running int32 // whether LightChain is running or stopped + procInterrupt int32 // interrupts chain insert + disableCheckFreq int32 // disables header verification } // NewLightChain returns a fully initialised light chain using information // available in the database. It initialises the default Ethereum header // validator. -func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.Engine) (*LightChain, error) { +func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.Engine, checkpoint *params.TrustedCheckpoint) (*LightChain, error) { bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) blockCache, _ := lru.New(blockCacheLimit) @@ -102,8 +101,8 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus. if bc.genesisBlock == nil { return nil, core.ErrNoGenesis } - if cp, ok := params.TrustedCheckpoints[bc.genesisBlock.Hash()]; ok { - bc.addTrustedCheckpoint(cp) + if checkpoint != nil { + bc.AddTrustedCheckpoint(checkpoint) } if err := bc.loadLastState(); err != nil { return nil, err @@ -119,46 +118,46 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus. return bc, nil } -// addTrustedCheckpoint adds a trusted checkpoint to the blockchain -func (self *LightChain) addTrustedCheckpoint(cp *params.TrustedCheckpoint) { - if self.odr.ChtIndexer() != nil { - StoreChtRoot(self.chainDb, cp.SectionIndex, cp.SectionHead, cp.CHTRoot) - self.odr.ChtIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) +// AddTrustedCheckpoint adds a trusted checkpoint to the blockchain +func (lc *LightChain) AddTrustedCheckpoint(cp *params.TrustedCheckpoint) { + if lc.odr.ChtIndexer() != nil { + StoreChtRoot(lc.chainDb, cp.SectionIndex, cp.SectionHead, cp.CHTRoot) + lc.odr.ChtIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) } - if self.odr.BloomTrieIndexer() != nil { - StoreBloomTrieRoot(self.chainDb, cp.SectionIndex, cp.SectionHead, cp.BloomRoot) - self.odr.BloomTrieIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) + if lc.odr.BloomTrieIndexer() != nil { + StoreBloomTrieRoot(lc.chainDb, cp.SectionIndex, cp.SectionHead, cp.BloomRoot) + lc.odr.BloomTrieIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) } - if self.odr.BloomIndexer() != nil { - self.odr.BloomIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) + if lc.odr.BloomIndexer() != nil { + lc.odr.BloomIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) } - log.Info("Added trusted checkpoint", "chain", cp.Name, "block", (cp.SectionIndex+1)*self.indexerConfig.ChtSize-1, "hash", cp.SectionHead) + log.Info("Added trusted checkpoint", "block", (cp.SectionIndex+1)*lc.indexerConfig.ChtSize-1, "hash", cp.SectionHead) } -func (self *LightChain) getProcInterrupt() bool { - return atomic.LoadInt32(&self.procInterrupt) == 1 +func (lc *LightChain) getProcInterrupt() bool { + return atomic.LoadInt32(&lc.procInterrupt) == 1 } // Odr returns the ODR backend of the chain -func (self *LightChain) Odr() OdrBackend { - return self.odr +func (lc *LightChain) Odr() OdrBackend { + return lc.odr } // loadLastState loads the last known chain state from the database. This method // assumes that the chain manager mutex is held. -func (self *LightChain) loadLastState() error { - if head := rawdb.ReadHeadHeaderHash(self.chainDb); head == (common.Hash{}) { +func (lc *LightChain) loadLastState() error { + if head := rawdb.ReadHeadHeaderHash(lc.chainDb); head == (common.Hash{}) { // Corrupt or empty database, init from scratch - self.Reset() + lc.Reset() } else { - if header := self.GetHeaderByHash(head); header != nil { - self.hc.SetCurrentHeader(header) + if header := lc.GetHeaderByHash(head); header != nil { + lc.hc.SetCurrentHeader(header) } } // Issue a status log and return - header := self.hc.CurrentHeader() - headerTd := self.GetTd(header.Hash(), header.Number.Uint64()) + header := lc.hc.CurrentHeader() + headerTd := lc.GetTd(header.Hash(), header.Number.Uint64()) log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(header.Time), 0))) return nil @@ -166,181 +165,180 @@ func (self *LightChain) loadLastState() error { // SetHead rewinds the local chain to a new head. Everything above the new // head will be deleted and the new one set. -func (bc *LightChain) SetHead(head uint64) { - bc.mu.Lock() - defer bc.mu.Unlock() +func (lc *LightChain) SetHead(head uint64) error { + lc.chainmu.Lock() + defer lc.chainmu.Unlock() - bc.hc.SetHead(head, nil) - bc.loadLastState() + lc.hc.SetHead(head, nil, nil) + return lc.loadLastState() } // GasLimit returns the gas limit of the current HEAD block. -func (self *LightChain) GasLimit() uint64 { - return self.hc.CurrentHeader().GasLimit +func (lc *LightChain) GasLimit() uint64 { + return lc.hc.CurrentHeader().GasLimit } // Reset purges the entire blockchain, restoring it to its genesis state. -func (bc *LightChain) Reset() { - bc.ResetWithGenesisBlock(bc.genesisBlock) +func (lc *LightChain) Reset() { + lc.ResetWithGenesisBlock(lc.genesisBlock) } // ResetWithGenesisBlock purges the entire blockchain, restoring it to the // specified genesis state. -func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { +func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { // Dump the entire block chain and purge the caches - bc.SetHead(0) + lc.SetHead(0) - bc.mu.Lock() - defer bc.mu.Unlock() + lc.chainmu.Lock() + defer lc.chainmu.Unlock() // Prepare the genesis block and reinitialise the chain - rawdb.WriteTd(bc.chainDb, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) - rawdb.WriteBlock(bc.chainDb, genesis) + rawdb.WriteTd(lc.chainDb, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) + rawdb.WriteBlock(lc.chainDb, genesis) - bc.genesisBlock = genesis - bc.hc.SetGenesis(bc.genesisBlock.Header()) - bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) + lc.genesisBlock = genesis + lc.hc.SetGenesis(lc.genesisBlock.Header()) + lc.hc.SetCurrentHeader(lc.genesisBlock.Header()) } // Accessors // Engine retrieves the light chain's consensus engine. -func (bc *LightChain) Engine() consensus.Engine { return bc.engine } +func (lc *LightChain) Engine() consensus.Engine { return lc.engine } // Genesis returns the genesis block -func (bc *LightChain) Genesis() *types.Block { - return bc.genesisBlock +func (lc *LightChain) Genesis() *types.Block { + return lc.genesisBlock } -// State returns a new mutable state based on the current HEAD block. -func (bc *LightChain) State() (*state.StateDB, error) { - return nil, errors.New("not implemented, needs client/server interface split") +func (lc *LightChain) StateCache() state.Database { + panic("not implemented") } // GetBody retrieves a block body (transactions and uncles) from the database // or ODR service by hash, caching it if found. -func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) { +func (lc *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) { // Short circuit if the body's already in the cache, retrieve otherwise - if cached, ok := self.bodyCache.Get(hash); ok { + if cached, ok := lc.bodyCache.Get(hash); ok { body := cached.(*types.Body) return body, nil } - number := self.hc.GetBlockNumber(hash) + number := lc.hc.GetBlockNumber(hash) if number == nil { return nil, errors.New("unknown block") } - body, err := GetBody(ctx, self.odr, hash, *number) + body, err := GetBody(ctx, lc.odr, hash, *number) if err != nil { return nil, err } // Cache the found body for next time and return - self.bodyCache.Add(hash, body) + lc.bodyCache.Add(hash, body) return body, nil } // GetBodyRLP retrieves a block body in RLP encoding from the database or // ODR service by hash, caching it if found. -func (self *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) { +func (lc *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) { // Short circuit if the body's already in the cache, retrieve otherwise - if cached, ok := self.bodyRLPCache.Get(hash); ok { + if cached, ok := lc.bodyRLPCache.Get(hash); ok { return cached.(rlp.RawValue), nil } - number := self.hc.GetBlockNumber(hash) + number := lc.hc.GetBlockNumber(hash) if number == nil { return nil, errors.New("unknown block") } - body, err := GetBodyRLP(ctx, self.odr, hash, *number) + body, err := GetBodyRLP(ctx, lc.odr, hash, *number) if err != nil { return nil, err } // Cache the found body for next time and return - self.bodyRLPCache.Add(hash, body) + lc.bodyRLPCache.Add(hash, body) return body, nil } // HasBlock checks if a block is fully present in the database or not, caching // it if present. -func (bc *LightChain) HasBlock(hash common.Hash, number uint64) bool { - blk, _ := bc.GetBlock(NoOdr, hash, number) +func (lc *LightChain) HasBlock(hash common.Hash, number uint64) bool { + blk, _ := lc.GetBlock(NoOdr, hash, number) return blk != nil } // GetBlock retrieves a block from the database or ODR service by hash and number, // caching it if found. -func (self *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) { +func (lc *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) { // Short circuit if the block's already in the cache, retrieve otherwise - if block, ok := self.blockCache.Get(hash); ok { + if block, ok := lc.blockCache.Get(hash); ok { return block.(*types.Block), nil } - block, err := GetBlock(ctx, self.odr, hash, number) + block, err := GetBlock(ctx, lc.odr, hash, number) if err != nil { return nil, err } // Cache the found block for next time and return - self.blockCache.Add(block.Hash(), block) + lc.blockCache.Add(block.Hash(), block) return block, nil } // GetBlockByHash retrieves a block from the database or ODR service by hash, // caching it if found. -func (self *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - number := self.hc.GetBlockNumber(hash) +func (lc *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + number := lc.hc.GetBlockNumber(hash) if number == nil { return nil, errors.New("unknown block") } - return self.GetBlock(ctx, hash, *number) + return lc.GetBlock(ctx, hash, *number) } // GetBlockByNumber retrieves a block from the database or ODR service by // number, caching it (associated with its hash) if found. -func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) { - hash, err := GetCanonicalHash(ctx, self.odr, number) +func (lc *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) { + hash, err := GetCanonicalHash(ctx, lc.odr, number) if hash == (common.Hash{}) || err != nil { return nil, err } - return self.GetBlock(ctx, hash, number) + return lc.GetBlock(ctx, hash, number) } // Stop stops the blockchain service. If any imports are currently in progress // it will abort them using the procInterrupt. -func (bc *LightChain) Stop() { - if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) { +func (lc *LightChain) Stop() { + if !atomic.CompareAndSwapInt32(&lc.running, 0, 1) { return } - close(bc.quit) - atomic.StoreInt32(&bc.procInterrupt, 1) + close(lc.quit) + atomic.StoreInt32(&lc.procInterrupt, 1) - bc.wg.Wait() + lc.wg.Wait() log.Info("Blockchain manager stopped") } // Rollback is designed to remove a chain of links from the database that aren't // certain enough to be valid. -func (self *LightChain) Rollback(chain []common.Hash) { - self.mu.Lock() - defer self.mu.Unlock() +func (lc *LightChain) Rollback(chain []common.Hash) { + lc.chainmu.Lock() + defer lc.chainmu.Unlock() for i := len(chain) - 1; i >= 0; i-- { hash := chain[i] - if head := self.hc.CurrentHeader(); head.Hash() == hash { - self.hc.SetCurrentHeader(self.GetHeader(head.ParentHash, head.Number.Uint64()-1)) + if head := lc.hc.CurrentHeader(); head.Hash() == hash { + lc.hc.SetCurrentHeader(lc.GetHeader(head.ParentHash, head.Number.Uint64()-1)) } } } // postChainEvents iterates over the events generated by a chain insertion and // posts them into the event feed. -func (self *LightChain) postChainEvents(events []interface{}) { +func (lc *LightChain) postChainEvents(events []interface{}) { for _, event := range events { switch ev := event.(type) { case core.ChainEvent: - if self.CurrentHeader().Hash() == ev.Hash { - self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block}) + if lc.CurrentHeader().Hash() == ev.Hash { + lc.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block}) } - self.chainFeed.Send(ev) + lc.chainFeed.Send(ev) case core.ChainSideEvent: - self.chainSideFeed.Send(ev) + lc.chainSideFeed.Send(ev) } } } @@ -356,31 +354,25 @@ func (self *LightChain) postChainEvents(events []interface{}) { // // In the case of a light chain, InsertHeaderChain also creates and posts light // chain events when necessary. -func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { - if self.disableCheckFreq { +func (lc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { + if atomic.LoadInt32(&lc.disableCheckFreq) == 1 { checkFreq = 0 } start := time.Now() - if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil { + if i, err := lc.hc.ValidateHeaderChain(chain, checkFreq); err != nil { return i, err } // Make sure only one thread manipulates the chain at once - self.chainmu.Lock() - defer func() { - self.chainmu.Unlock() - time.Sleep(time.Millisecond * 10) // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation - }() + lc.chainmu.Lock() + defer lc.chainmu.Unlock() - self.wg.Add(1) - defer self.wg.Done() + lc.wg.Add(1) + defer lc.wg.Done() var events []interface{} whFunc := func(header *types.Header) error { - self.mu.Lock() - defer self.mu.Unlock() - - status, err := self.hc.WriteHeader(header) + status, err := lc.hc.WriteHeader(header) switch status { case core.CanonStatTy: @@ -393,51 +385,51 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) } return err } - i, err := self.hc.InsertHeaderChain(chain, whFunc, start) - self.postChainEvents(events) + i, err := lc.hc.InsertHeaderChain(chain, whFunc, start) + lc.postChainEvents(events) return i, err } // CurrentHeader retrieves the current head header of the canonical chain. The // header is retrieved from the HeaderChain's internal cache. -func (self *LightChain) CurrentHeader() *types.Header { - return self.hc.CurrentHeader() +func (lc *LightChain) CurrentHeader() *types.Header { + return lc.hc.CurrentHeader() } // GetTd retrieves a block's total difficulty in the canonical chain from the // database by hash and number, caching it if found. -func (self *LightChain) GetTd(hash common.Hash, number uint64) *big.Int { - return self.hc.GetTd(hash, number) +func (lc *LightChain) GetTd(hash common.Hash, number uint64) *big.Int { + return lc.hc.GetTd(hash, number) } // GetTdByHash retrieves a block's total difficulty in the canonical chain from the // database by hash, caching it if found. -func (self *LightChain) GetTdByHash(hash common.Hash) *big.Int { - return self.hc.GetTdByHash(hash) +func (lc *LightChain) GetTdByHash(hash common.Hash) *big.Int { + return lc.hc.GetTdByHash(hash) } // GetHeader retrieves a block header from the database by hash and number, // caching it if found. -func (self *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header { - return self.hc.GetHeader(hash, number) +func (lc *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header { + return lc.hc.GetHeader(hash, number) } // GetHeaderByHash retrieves a block header from the database by hash, caching it if // found. -func (self *LightChain) GetHeaderByHash(hash common.Hash) *types.Header { - return self.hc.GetHeaderByHash(hash) +func (lc *LightChain) GetHeaderByHash(hash common.Hash) *types.Header { + return lc.hc.GetHeaderByHash(hash) } // HasHeader checks if a block header is present in the database or not, caching // it if present. -func (bc *LightChain) HasHeader(hash common.Hash, number uint64) bool { - return bc.hc.HasHeader(hash, number) +func (lc *LightChain) HasHeader(hash common.Hash, number uint64) bool { + return lc.hc.HasHeader(hash, number) } // GetBlockHashesFromHash retrieves a number of block hashes starting at a given // hash, fetching towards the genesis block. -func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { - return self.hc.GetBlockHashesFromHash(hash, max) +func (lc *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { + return lc.hc.GetBlockHashesFromHash(hash, max) } // GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or @@ -445,56 +437,53 @@ func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []c // number of blocks to be individually checked before we reach the canonical chain. // // Note: ancestor == 0 returns the same block, 1 returns its parent and so on. -func (bc *LightChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - bc.chainmu.Lock() - defer bc.chainmu.Unlock() - - return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) +func (lc *LightChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { + return lc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) } // GetHeaderByNumber retrieves a block header from the database by number, // caching it (associated with its hash) if found. -func (self *LightChain) GetHeaderByNumber(number uint64) *types.Header { - return self.hc.GetHeaderByNumber(number) +func (lc *LightChain) GetHeaderByNumber(number uint64) *types.Header { + return lc.hc.GetHeaderByNumber(number) } // GetHeaderByNumberOdr retrieves a block header from the database or network // by number, caching it (associated with its hash) if found. -func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) { - if header := self.hc.GetHeaderByNumber(number); header != nil { +func (lc *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) { + if header := lc.hc.GetHeaderByNumber(number); header != nil { return header, nil } - return GetHeaderByNumber(ctx, self.odr, number) + return GetHeaderByNumber(ctx, lc.odr, number) } // Config retrieves the header chain's chain configuration. -func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() } +func (lc *LightChain) Config() *params.ChainConfig { return lc.hc.Config() } -func (self *LightChain) SyncCht(ctx context.Context) bool { - // If we don't have a CHT indexer, abort - if self.odr.ChtIndexer() == nil { - return false - } - // Ensure the remote CHT head is ahead of us - head := self.CurrentHeader().Number.Uint64() - sections, _, _ := self.odr.ChtIndexer().Sections() +// SyncCheckpoint fetches the checkpoint point block header according to +// the checkpoint provided by the remote peer. +// +// Note if we are running the clique, fetches the last epoch snapshot header +// which covered by checkpoint. +func (lc *LightChain) SyncCheckpoint(ctx context.Context, checkpoint *params.TrustedCheckpoint) bool { + // Ensure the remote checkpoint head is ahead of us + head := lc.CurrentHeader().Number.Uint64() - latest := sections*self.indexerConfig.ChtSize - 1 - if clique := self.hc.Config().Clique; clique != nil { + latest := (checkpoint.SectionIndex+1)*lc.indexerConfig.ChtSize - 1 + if clique := lc.hc.Config().Clique; clique != nil { latest -= latest % clique.Epoch // epoch snapshot for clique } if head >= latest { - return false + return true } // Retrieve the latest useful header and update to it - if header, err := GetHeaderByNumber(ctx, self.odr, latest); header != nil && err == nil { - self.mu.Lock() - defer self.mu.Unlock() + if header, err := GetHeaderByNumber(ctx, lc.odr, latest); header != nil && err == nil { + lc.chainmu.Lock() + defer lc.chainmu.Unlock() // Ensure the chain didn't move past the latest block while retrieving it - if self.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { + if lc.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { log.Info("Updated latest header based on CHT", "number", header.Number, "hash", header.Hash(), "age", common.PrettyAge(time.Unix(int64(header.Time), 0))) - self.hc.SetCurrentHeader(header) + lc.hc.SetCurrentHeader(header) } return true } @@ -503,52 +492,48 @@ func (self *LightChain) SyncCht(ctx context.Context) bool { // LockChain locks the chain mutex for reading so that multiple canonical hashes can be // retrieved while it is guaranteed that they belong to the same version of the chain -func (self *LightChain) LockChain() { - self.chainmu.RLock() +func (lc *LightChain) LockChain() { + lc.chainmu.RLock() } // UnlockChain unlocks the chain mutex -func (self *LightChain) UnlockChain() { - self.chainmu.RUnlock() +func (lc *LightChain) UnlockChain() { + lc.chainmu.RUnlock() } // SubscribeChainEvent registers a subscription of ChainEvent. -func (self *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - return self.scope.Track(self.chainFeed.Subscribe(ch)) +func (lc *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + return lc.scope.Track(lc.chainFeed.Subscribe(ch)) } // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. -func (self *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - return self.scope.Track(self.chainHeadFeed.Subscribe(ch)) +func (lc *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { + return lc.scope.Track(lc.chainHeadFeed.Subscribe(ch)) } // SubscribeChainSideEvent registers a subscription of ChainSideEvent. -func (self *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { - return self.scope.Track(self.chainSideFeed.Subscribe(ch)) +func (lc *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { + return lc.scope.Track(lc.chainSideFeed.Subscribe(ch)) } // SubscribeLogsEvent implements the interface of filters.Backend // LightChain does not send logs events, so return an empty subscription. -func (self *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return self.scope.Track(new(event.Feed).Subscribe(ch)) +func (lc *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { + return lc.scope.Track(new(event.Feed).Subscribe(ch)) } // SubscribeRemovedLogsEvent implements the interface of filters.Backend // LightChain does not send core.RemovedLogsEvent, so return an empty subscription. -func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - return self.scope.Track(new(event.Feed).Subscribe(ch)) +func (lc *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { + return lc.scope.Track(new(event.Feed).Subscribe(ch)) } -//DisableCheckFreq disables header validation. It needs for ULC -func (self *LightChain) DisableCheckFreq() { - self.mu.Lock() - defer self.mu.Unlock() - self.disableCheckFreq = true +// DisableCheckFreq disables header validation. This is used for ultralight mode. +func (lc *LightChain) DisableCheckFreq() { + atomic.StoreInt32(&lc.disableCheckFreq, 1) } -//EnableCheckFreq enables header validation -func (self *LightChain) EnableCheckFreq() { - self.mu.Lock() - defer self.mu.Unlock() - self.disableCheckFreq = false +// EnableCheckFreq enables header validation. +func (lc *LightChain) EnableCheckFreq() { + atomic.StoreInt32(&lc.disableCheckFreq, 0) } diff --git a/vendor/github.com/ethereum/go-ethereum/light/nodeset.go b/vendor/github.com/ethereum/go-ethereum/light/nodeset.go index 6f25219c1..366259678 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/nodeset.go +++ b/vendor/github.com/ethereum/go-ethereum/light/nodeset.go @@ -60,6 +60,15 @@ func (db *NodeSet) Put(key []byte, value []byte) error { return nil } +// Delete removes a node from the set +func (db *NodeSet) Delete(key []byte) error { + db.lock.Lock() + defer db.lock.Unlock() + + delete(db.nodes, string(key)) + return nil +} + // Get returns a stored node func (db *NodeSet) Get(key []byte) ([]byte, error) { db.lock.RLock() @@ -106,7 +115,7 @@ func (db *NodeSet) NodeList() NodeList { } // Store writes the contents of the set to the given database -func (db *NodeSet) Store(target ethdb.Putter) { +func (db *NodeSet) Store(target ethdb.KeyValueWriter) { db.lock.RLock() defer db.lock.RUnlock() @@ -115,11 +124,11 @@ func (db *NodeSet) Store(target ethdb.Putter) { } } -// NodeList stores an ordered list of trie nodes. It implements ethdb.Putter. +// NodeList stores an ordered list of trie nodes. It implements ethdb.KeyValueWriter. type NodeList []rlp.RawValue // Store writes the contents of the list to the given database -func (n NodeList) Store(db ethdb.Putter) { +func (n NodeList) Store(db ethdb.KeyValueWriter) { for _, node := range n { db.Put(crypto.Keccak256(node), node) } @@ -138,6 +147,11 @@ func (n *NodeList) Put(key []byte, value []byte) error { return nil } +// Delete panics as there's no reason to remove a node from the list. +func (n *NodeList) Delete(key []byte) error { + panic("not supported") +} + // DataSize returns the aggregated data size of nodes in the list func (n NodeList) DataSize() int { var size int diff --git a/vendor/github.com/ethereum/go-ethereum/light/odr.go b/vendor/github.com/ethereum/go-ethereum/light/odr.go index 900be0544..907712ede 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/odr.go +++ b/vendor/github.com/ethereum/go-ethereum/light/odr.go @@ -14,8 +14,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package light implements on-demand retrieval capable state and chain objects -// for the Ethereum Light Client. package light import ( @@ -124,19 +122,25 @@ func (req *BlockRequest) StoreResult(db ethdb.Database) { // ReceiptsRequest is the ODR request type for retrieving block bodies type ReceiptsRequest struct { OdrRequest - Hash common.Hash - Number uint64 - Receipts types.Receipts + Untrusted bool // Indicator whether the result retrieved is trusted or not + Hash common.Hash + Number uint64 + Header *types.Header + Receipts types.Receipts } // StoreResult stores the retrieved data in local database func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { - rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) + if !req.Untrusted { + rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) + } } // ChtRequest is the ODR request type for state/storage trie entries type ChtRequest struct { OdrRequest + Untrusted bool // Indicator whether the result retrieved is trusted or not + PeerId string // The specified peer id from which to retrieve data. Config *IndexerConfig ChtNum, BlockNum uint64 ChtRoot common.Hash @@ -149,9 +153,11 @@ type ChtRequest struct { func (req *ChtRequest) StoreResult(db ethdb.Database) { hash, num := req.Header.Hash(), req.Header.Number.Uint64() - rawdb.WriteHeader(db, req.Header) - rawdb.WriteTd(db, hash, num, req.Td) - rawdb.WriteCanonicalHash(db, hash, num) + if !req.Untrusted { + rawdb.WriteHeader(db, req.Header) + rawdb.WriteTd(db, hash, num, req.Td) + rawdb.WriteCanonicalHash(db, hash, num) + } } // BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure @@ -177,3 +183,20 @@ func (req *BloomRequest) StoreResult(db ethdb.Database) { rawdb.WriteBloomBits(db, req.BitIdx, sectionIdx, sectionHead, req.BloomBits[i]) } } + +// TxStatus describes the status of a transaction +type TxStatus struct { + Status core.TxStatus + Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"` + Error string +} + +// TxStatusRequest is the ODR request type for retrieving transaction status +type TxStatusRequest struct { + OdrRequest + Hashes []common.Hash + Status []TxStatus +} + +// StoreResult stores the retrieved data in local database +func (req *TxStatusRequest) StoreResult(db ethdb.Database) {} diff --git a/vendor/github.com/ethereum/go-ethereum/light/odr_util.go b/vendor/github.com/ethereum/go-ethereum/light/odr_util.go index 073f0d642..2c820d40c 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/odr_util.go +++ b/vendor/github.com/ethereum/go-ethereum/light/odr_util.go @@ -28,7 +28,7 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -var sha3_nil = crypto.Keccak256Hash(nil) +var sha3Nil = crypto.Keccak256Hash(nil) func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { db := odr.Database() @@ -60,7 +60,7 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ } } if number >= chtCount*odr.IndexerConfig().ChtSize { - return nil, ErrNoTrustedCht + return nil, errNoTrustedCht } r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number, Config: odr.IndexerConfig()} if err := odr.Retrieve(ctx, r); err != nil { @@ -69,6 +69,16 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ return r.Header, nil } +// GetUntrustedHeaderByNumber fetches specified block header without correctness checking. +// Note this function should only be used in light client checkpoint syncing. +func GetUntrustedHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64, peerId string) (*types.Header, error) { + r := &ChtRequest{BlockNum: number, ChtNum: number / odr.IndexerConfig().ChtSize, Untrusted: true, PeerId: peerId, Config: odr.IndexerConfig()} + if err := odr.Retrieve(ctx, r); err != nil { + return nil, err + } + return r.Header, nil +} + func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) { hash := rawdb.ReadCanonicalHash(odr.Database(), number) if (hash != common.Hash{}) { @@ -114,7 +124,7 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint // Retrieve the block header and body contents header := rawdb.ReadHeader(odr.Database(), hash, number) if header == nil { - return nil, ErrNoHeader + return nil, errNoHeader } body, err := GetBody(ctx, odr, hash, number) if err != nil { @@ -127,8 +137,8 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint // GetBlockReceipts retrieves the receipts generated by the transactions included // in a block given by its hash. func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) { - // Retrieve the potentially incomplete receipts from disk or network - receipts := rawdb.ReadReceipts(odr.Database(), hash, number) + // Assume receipts are already stored locally and attempt to retrieve. + receipts := rawdb.ReadRawReceipts(odr.Database(), hash, number) if receipts == nil { r := &ReceiptsRequest{Hash: hash, Number: number} if err := odr.Retrieve(ctx, r); err != nil { @@ -145,7 +155,7 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num genesis := rawdb.ReadCanonicalHash(odr.Database(), 0) config := rawdb.ReadChainConfig(odr.Database(), genesis) - if err := core.SetReceiptsData(config, block, receipts); err != nil { + if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Transactions()); err != nil { return nil, err } rawdb.WriteReceipts(odr.Database(), hash, number, receipts) @@ -157,13 +167,33 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num // block given by its hash. func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) ([][]*types.Log, error) { // Retrieve the potentially incomplete receipts from disk or network - receipts := rawdb.ReadReceipts(odr.Database(), hash, number) + receipts, err := GetBlockReceipts(ctx, odr, hash, number) + if err != nil { + return nil, err + } + // Return the logs without deriving any computed fields on the receipts + logs := make([][]*types.Log, len(receipts)) + for i, receipt := range receipts { + logs[i] = receipt.Logs + } + return logs, nil +} + +// GetUntrustedBlockLogs retrieves the logs generated by the transactions included in a +// block. The retrieved logs are regarded as untrusted and will not be stored in the +// database. This function should only be used in light client checkpoint syncing. +func GetUntrustedBlockLogs(ctx context.Context, odr OdrBackend, header *types.Header) ([][]*types.Log, error) { + // Retrieve the potentially incomplete receipts from disk or network + hash, number := header.Hash(), header.Number.Uint64() + receipts := rawdb.ReadRawReceipts(odr.Database(), hash, number) if receipts == nil { - r := &ReceiptsRequest{Hash: hash, Number: number} + r := &ReceiptsRequest{Hash: hash, Number: number, Header: header, Untrusted: true} if err := odr.Retrieve(ctx, r); err != nil { return nil, err } receipts = r.Receipts + // Untrusted receipts won't be stored in the database. Therefore + // derived fields computation is unnecessary. } // Return the logs without deriving any computed fields on the receipts logs := make([][]*types.Log, len(receipts)) @@ -211,7 +241,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi } else { // TODO(rjl493456442) Convert sectionIndex to BloomTrie relative index if sectionIdx >= bloomTrieCount { - return nil, ErrNoTrustedBloomTrie + return nil, errNoTrustedBloomTrie } reqList = append(reqList, sectionIdx) reqIdx = append(reqIdx, i) @@ -232,3 +262,23 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi return result, nil } } + +// GetTransaction retrieves a canonical transaction by hash and also returns its position in the chain +func GetTransaction(ctx context.Context, odr OdrBackend, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { + r := &TxStatusRequest{Hashes: []common.Hash{txHash}} + if err := odr.Retrieve(ctx, r); err != nil || r.Status[0].Status != core.TxStatusIncluded { + return nil, common.Hash{}, 0, 0, err + } else { + pos := r.Status[0].Lookup + // first ensure that we have the header, otherwise block body retrieval will fail + // also verify if this is a canonical block by getting the header by number and checking its hash + if header, err := GetHeaderByNumber(ctx, odr, pos.BlockIndex); err != nil || header.Hash() != pos.BlockHash { + return nil, common.Hash{}, 0, 0, err + } + if body, err := GetBody(ctx, odr, pos.BlockHash, pos.BlockIndex); err != nil || uint64(len(body.Transactions)) <= pos.Index || body.Transactions[pos.Index].Hash() != txHash { + return nil, common.Hash{}, 0, 0, err + } else { + return body.Transactions[pos.Index], pos.BlockHash, pos.BlockIndex, pos.Index, nil + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/light/postprocess.go b/vendor/github.com/ethereum/go-ethereum/light/postprocess.go index 8e0495566..083dcfceb 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/postprocess.go +++ b/vendor/github.com/ethereum/go-ethereum/light/postprocess.go @@ -41,9 +41,6 @@ type IndexerConfig struct { // The block frequency for creating CHTs. ChtSize uint64 - // A special auxiliary field represents client's chtsize for server config, otherwise represents server's chtsize. - PairChtSize uint64 - // The number of confirmations needed to generate/accept a canonical hash help trie. ChtConfirms uint64 @@ -64,8 +61,7 @@ type IndexerConfig struct { var ( // DefaultServerIndexerConfig wraps a set of configs as a default indexer config for server side. DefaultServerIndexerConfig = &IndexerConfig{ - ChtSize: params.CHTFrequencyServer, - PairChtSize: params.CHTFrequencyClient, + ChtSize: params.CHTFrequency, ChtConfirms: params.HelperTrieProcessConfirmations, BloomSize: params.BloomBitsBlocks, BloomConfirms: params.BloomConfirms, @@ -74,8 +70,7 @@ var ( } // DefaultClientIndexerConfig wraps a set of configs as a default indexer config for client side. DefaultClientIndexerConfig = &IndexerConfig{ - ChtSize: params.CHTFrequencyClient, - PairChtSize: params.CHTFrequencyServer, + ChtSize: params.CHTFrequency, ChtConfirms: params.HelperTrieConfirmations, BloomSize: params.BloomBitsBlocksClient, BloomConfirms: params.HelperTrieConfirmations, @@ -84,8 +79,7 @@ var ( } // TestServerIndexerConfig wraps a set of configs as a test indexer config for server side. TestServerIndexerConfig = &IndexerConfig{ - ChtSize: 64, - PairChtSize: 512, + ChtSize: 512, ChtConfirms: 4, BloomSize: 64, BloomConfirms: 4, @@ -95,7 +89,6 @@ var ( // TestClientIndexerConfig wraps a set of configs as a test indexer config for client side. TestClientIndexerConfig = &IndexerConfig{ ChtSize: 512, - PairChtSize: 64, ChtConfirms: 32, BloomSize: 512, BloomConfirms: 32, @@ -105,10 +98,10 @@ var ( ) var ( - ErrNoTrustedCht = errors.New("no trusted canonical hash trie") - ErrNoTrustedBloomTrie = errors.New("no trusted bloom trie") - ErrNoHeader = errors.New("header not found") - chtPrefix = []byte("chtRoot-") // chtPrefix + chtNum (uint64 big endian) -> trie root hash + errNoTrustedCht = errors.New("no trusted canonical hash trie") + errNoTrustedBloomTrie = errors.New("no trusted bloom trie") + errNoHeader = errors.New("header not found") + chtPrefix = []byte("chtRootV2-") // chtPrefix + chtNum (uint64 big endian) -> trie root hash ChtTablePrefix = "cht-" ) @@ -119,7 +112,6 @@ type ChtNode struct { } // GetChtRoot reads the CHT root associated to the given section from the database -// Note that sectionIdx is specified according to LES/1 CHT section size. func GetChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) common.Hash { var encNumber [8]byte binary.BigEndian.PutUint64(encNumber[:], sectionIdx) @@ -128,7 +120,6 @@ func GetChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) c } // StoreChtRoot writes the CHT root associated to the given section into the database -// Note that sectionIdx is specified according to LES/1 CHT section size. func StoreChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead, root common.Hash) { var encNumber [8]byte binary.BigEndian.PutUint64(encNumber[:], sectionIdx) @@ -147,7 +138,7 @@ type ChtIndexerBackend struct { // NewChtIndexer creates a Cht chain indexer func NewChtIndexer(db ethdb.Database, odr OdrBackend, size, confirms uint64) *core.ChainIndexer { - trieTable := ethdb.NewTable(db, ChtTablePrefix) + trieTable := rawdb.NewTable(db, ChtTablePrefix) backend := &ChtIndexerBackend{ diskdb: db, odr: odr, @@ -155,7 +146,7 @@ func NewChtIndexer(db ethdb.Database, odr OdrBackend, size, confirms uint64) *co triedb: trie.NewDatabaseWithCache(trieTable, 1), // Use a tiny cache only to keep memory down sectionSize: size, } - return core.NewChainIndexer(db, ethdb.NewTable(db, "chtIndex-"), backend, size, confirms, time.Millisecond*100, "cht") + return core.NewChainIndexer(db, rawdb.NewTable(db, "chtIndexV2-"), backend, size, confirms, time.Millisecond*100, "cht") } // fetchMissingNodes tries to retrieve the last entry of the latest trusted CHT from the @@ -227,9 +218,7 @@ func (c *ChtIndexerBackend) Commit() error { } c.triedb.Commit(root, false) - if ((c.section+1)*c.sectionSize)%params.CHTFrequencyClient == 0 { - log.Info("Storing CHT", "section", c.section*c.sectionSize/params.CHTFrequencyClient, "head", fmt.Sprintf("%064x", c.lastHash), "root", fmt.Sprintf("%064x", root)) - } + log.Info("Storing CHT", "section", c.section, "head", fmt.Sprintf("%064x", c.lastHash), "root", fmt.Sprintf("%064x", root)) StoreChtRoot(c.diskdb, c.section, c.lastHash, root) return nil } @@ -269,7 +258,7 @@ type BloomTrieIndexerBackend struct { // NewBloomTrieIndexer creates a BloomTrie chain indexer func NewBloomTrieIndexer(db ethdb.Database, odr OdrBackend, parentSize, size uint64) *core.ChainIndexer { - trieTable := ethdb.NewTable(db, BloomTrieTablePrefix) + trieTable := rawdb.NewTable(db, BloomTrieTablePrefix) backend := &BloomTrieIndexerBackend{ diskdb: db, odr: odr, @@ -280,7 +269,7 @@ func NewBloomTrieIndexer(db ethdb.Database, odr OdrBackend, parentSize, size uin } backend.bloomTrieRatio = size / parentSize backend.sectionHeads = make([]common.Hash, backend.bloomTrieRatio) - return core.NewChainIndexer(db, ethdb.NewTable(db, "bltIndex-"), backend, size, 0, time.Millisecond*100, "bloomtrie") + return core.NewChainIndexer(db, rawdb.NewTable(db, "bltIndex-"), backend, size, 0, time.Millisecond*100, "bloomtrie") } // fetchMissingNodes tries to retrieve the last entries of the latest trusted bloom trie from the diff --git a/vendor/github.com/ethereum/go-ethereum/light/trie.go b/vendor/github.com/ethereum/go-ethereum/light/trie.go index ab4e18b43..e512bf6f9 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/trie.go +++ b/vendor/github.com/ethereum/go-ethereum/light/trie.go @@ -67,7 +67,7 @@ func (db *odrDatabase) CopyTrie(t state.Trie) state.Trie { } func (db *odrDatabase) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { - if codeHash == sha3_nil { + if codeHash == sha3Nil { return nil, nil } if code, err := db.backend.Database().Get(codeHash[:]); err == nil { @@ -141,7 +141,7 @@ func (t *odrTrie) GetKey(sha []byte) []byte { return nil } -func (t *odrTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { +func (t *odrTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error { return errors.New("not implemented, needs client/server interface split") } diff --git a/vendor/github.com/ethereum/go-ethereum/light/txpool.go b/vendor/github.com/ethereum/go-ethereum/light/txpool.go index 767a797bd..11a0e76ae 100644 --- a/vendor/github.com/ethereum/go-ethereum/light/txpool.go +++ b/vendor/github.com/ethereum/go-ethereum/light/txpool.go @@ -19,6 +19,7 @@ package light import ( "context" "fmt" + "math/big" "sync" "time" @@ -67,7 +68,7 @@ type TxPool struct { mined map[common.Hash][]*types.Transaction // mined transactions by block hash clearIdx uint64 // earliest block nr that can contain mined tx info - homestead bool + istanbul bool // Fork indicator whether we are in the istanbul stage. } // TxRelayBackend provides an interface to the mechanism that forwards transacions @@ -309,8 +310,10 @@ func (pool *TxPool) setNewHead(head *types.Header) { txc, _ := pool.reorgOnNewHead(ctx, head) m, r := txc.getLists() pool.relay.NewHead(pool.head, m, r) - pool.homestead = pool.config.IsHomestead(head.Number) - pool.signer = types.MakeSigner(pool.config, head.Number) + + // Update fork indicator by next pending block number + next := new(big.Int).Add(head.Number, big.NewInt(1)) + pool.istanbul = pool.config.IsIstanbul(next) } // Stop stops the light transaction pool @@ -378,7 +381,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error } // Should supply enough intrinsic gas - gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) + gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, true, pool.istanbul) if err != nil { return err } @@ -390,81 +393,81 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error // add validates a new transaction and sets its state pending if processable. // It also updates the locally stored nonce if necessary. -func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error { +func (pool *TxPool) add(ctx context.Context, tx *types.Transaction) error { hash := tx.Hash() - if self.pending[hash] != nil { + if pool.pending[hash] != nil { return fmt.Errorf("Known transaction (%x)", hash[:4]) } - err := self.validateTx(ctx, tx) + err := pool.validateTx(ctx, tx) if err != nil { return err } - if _, ok := self.pending[hash]; !ok { - self.pending[hash] = tx + if _, ok := pool.pending[hash]; !ok { + pool.pending[hash] = tx nonce := tx.Nonce() + 1 - addr, _ := types.Sender(self.signer, tx) - if nonce > self.nonce[addr] { - self.nonce[addr] = nonce + addr, _ := types.Sender(pool.signer, tx) + if nonce > pool.nonce[addr] { + pool.nonce[addr] = nonce } // Notify the subscribers. This event is posted in a goroutine // because it's possible that somewhere during the post "Remove transaction" // gets called which will then wait for the global tx pool lock and deadlock. - go self.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}}) + go pool.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}}) } // Print a log message if low enough level is set - log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(self.signer, tx); return from }}, "to", tx.To()) + log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(pool.signer, tx); return from }}, "to", tx.To()) return nil } // Add adds a transaction to the pool if valid and passes it to the tx relay // backend -func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error { - self.mu.Lock() - defer self.mu.Unlock() +func (pool *TxPool) Add(ctx context.Context, tx *types.Transaction) error { + pool.mu.Lock() + defer pool.mu.Unlock() data, err := rlp.EncodeToBytes(tx) if err != nil { return err } - if err := self.add(ctx, tx); err != nil { + if err := pool.add(ctx, tx); err != nil { return err } //fmt.Println("Send", tx.Hash()) - self.relay.Send(types.Transactions{tx}) + pool.relay.Send(types.Transactions{tx}) - self.chainDb.Put(tx.Hash().Bytes(), data) + pool.chainDb.Put(tx.Hash().Bytes(), data) return nil } // AddTransactions adds all valid transactions to the pool and passes them to // the tx relay backend -func (self *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { - self.mu.Lock() - defer self.mu.Unlock() +func (pool *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { + pool.mu.Lock() + defer pool.mu.Unlock() var sendTx types.Transactions for _, tx := range txs { - if err := self.add(ctx, tx); err == nil { + if err := pool.add(ctx, tx); err == nil { sendTx = append(sendTx, tx) } } if len(sendTx) > 0 { - self.relay.Send(sendTx) + pool.relay.Send(sendTx) } } // GetTransaction returns a transaction if it is contained in the pool // and nil otherwise. -func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { +func (pool *TxPool) GetTransaction(hash common.Hash) *types.Transaction { // check the txs first - if tx, ok := tp.pending[hash]; ok { + if tx, ok := pool.pending[hash]; ok { return tx } return nil @@ -472,13 +475,13 @@ func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { // GetTransactions returns all currently processable transactions. // The returned slice may be modified by the caller. -func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { - self.mu.RLock() - defer self.mu.RUnlock() +func (pool *TxPool) GetTransactions() (txs types.Transactions, err error) { + pool.mu.RLock() + defer pool.mu.RUnlock() - txs = make(types.Transactions, len(self.pending)) + txs = make(types.Transactions, len(pool.pending)) i := 0 - for _, tx := range self.pending { + for _, tx := range pool.pending { txs[i] = tx i++ } @@ -487,14 +490,14 @@ func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { // Content retrieves the data content of the transaction pool, returning all the // pending as well as queued transactions, grouped by account and nonce. -func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { - self.mu.RLock() - defer self.mu.RUnlock() +func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { + pool.mu.RLock() + defer pool.mu.RUnlock() // Retrieve all the pending transactions and sort by account and by nonce pending := make(map[common.Address]types.Transactions) - for _, tx := range self.pending { - account, _ := types.Sender(self.signer, tx) + for _, tx := range pool.pending { + account, _ := types.Sender(pool.signer, tx) pending[account] = append(pending[account], tx) } // There are no queued transactions in a light pool, just return an empty map @@ -503,20 +506,20 @@ func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common } // RemoveTransactions removes all given transactions from the pool. -func (self *TxPool) RemoveTransactions(txs types.Transactions) { - self.mu.Lock() - defer self.mu.Unlock() +func (pool *TxPool) RemoveTransactions(txs types.Transactions) { + pool.mu.Lock() + defer pool.mu.Unlock() var hashes []common.Hash - batch := self.chainDb.NewBatch() + batch := pool.chainDb.NewBatch() for _, tx := range txs { hash := tx.Hash() - delete(self.pending, hash) + delete(pool.pending, hash) batch.Delete(hash.Bytes()) hashes = append(hashes, hash) } batch.Write() - self.relay.Discard(hashes) + pool.relay.Discard(hashes) } // RemoveTx removes the transaction with the given hash from the pool. diff --git a/vendor/github.com/ethereum/go-ethereum/log/format.go b/vendor/github.com/ethereum/go-ethereum/log/format.go index 5a028263f..53b3394fb 100644 --- a/vendor/github.com/ethereum/go-ethereum/log/format.go +++ b/vendor/github.com/ethereum/go-ethereum/log/format.go @@ -14,10 +14,11 @@ import ( ) const ( - timeFormat = "2006-01-02T15:04:05-0700" - termTimeFormat = "01-02|15:04:05.000" - floatFormat = 'f' - termMsgJust = 40 + timeFormat = "2006-01-02T15:04:05-0700" + termTimeFormat = "01-02|15:04:05.000" + floatFormat = 'f' + termMsgJust = 40 + termCtxMaxPadding = 40 ) // locationTrims are trimmed for display to avoid unwieldy log lines. @@ -161,6 +162,7 @@ func logfmt(buf *bytes.Buffer, ctx []interface{}, color int, term bool) { if !ok { k, v = errorKey, formatLogfmtValue(k, term) } + if color > 0 { fmt.Fprintf(buf, "\x1b[%dm%s\x1b[0m=", color, k) } else { diff --git a/vendor/github.com/ethereum/go-ethereum/core/rawdb/interfaces.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu.go similarity index 64% rename from vendor/github.com/ethereum/go-ethereum/core/rawdb/interfaces.go rename to vendor/github.com/ethereum/go-ethereum/metrics/cpu.go index 3bdf55124..a7bf8f5d0 100644 --- a/vendor/github.com/ethereum/go-ethereum/core/rawdb/interfaces.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu.go @@ -14,20 +14,16 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package rawdb +package metrics -// DatabaseReader wraps the Has and Get method of a backing data store. -type DatabaseReader interface { - Has(key []byte) (bool, error) - Get(key []byte) ([]byte, error) +// CPUStats is the system and process CPU stats. +type CPUStats struct { + GlobalTime int64 // Time spent by the CPU working on all processes + GlobalWait int64 // Time spent by waiting on disk for all processes + LocalTime int64 // Time spent by the CPU working on this process } -// DatabaseWriter wraps the Put method of a backing data store. -type DatabaseWriter interface { - Put(key []byte, value []byte) error -} - -// DatabaseDeleter wraps the Delete method of a backing data store. -type DatabaseDeleter interface { - Delete(key []byte) error +// ReadCPUStats retrieves the current CPU stats. +func ReadCPUStats(stats *CPUStats) { + readCPUStats(stats) } diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats.go new file mode 100644 index 000000000..35d396ae2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats.go @@ -0,0 +1,14 @@ +// +build !ios,!android + +package metrics + +import "github.com/elastic/gosigar" + +func readCPUStats(stats *CPUStats) { + global := gosigar.Cpu{} + global.Get() + + stats.GlobalTime = int64(global.User + global.Nice + global.Sys) + stats.GlobalWait = int64(global.Wait) + stats.LocalTime = getProcessCPUTime() +} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_android.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_android.go new file mode 100644 index 000000000..906bb56db --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_android.go @@ -0,0 +1,5 @@ +// +build android + +package metrics + +func readCPUStats(stats *CPUStats) {} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_ios.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_ios.go new file mode 100644 index 000000000..a60c22573 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_stats_ios.go @@ -0,0 +1,5 @@ +// +build ios + +package metrics + +func readCPUStats(stats *CPUStats) {} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/cpu_syscall.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_syscall.go new file mode 100644 index 000000000..e245453e8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_syscall.go @@ -0,0 +1,35 @@ +// 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 . + +// +build !windows + +package metrics + +import ( + "syscall" + + "github.com/ethereum/go-ethereum/log" +) + +// getProcessCPUTime retrieves the process' CPU time since program startup. +func getProcessCPUTime() int64 { + var usage syscall.Rusage + if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil { + log.Warn("Failed to retrieve CPU time", "err", err) + return 0 + } + return int64(usage.Utime.Sec+usage.Stime.Sec)*100 + int64(usage.Utime.Usec+usage.Stime.Usec)/10000 //nolint:unconvert +} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/cpu_windows.go b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_windows.go new file mode 100644 index 000000000..fb29a52a8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/cpu_windows.go @@ -0,0 +1,23 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package metrics + +// getProcessCPUTime returns 0 on Windows as there is no system call to resolve +// the actual process' CPU time. +func getProcessCPUTime() int64 { + return 0 +} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/exp/exp.go b/vendor/github.com/ethereum/go-ethereum/metrics/exp/exp.go index 325a193c7..55820f1aa 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/exp/exp.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/exp/exp.go @@ -9,6 +9,7 @@ import ( "sync" "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/metrics/prometheus" ) type exp struct { @@ -42,6 +43,7 @@ func Exp(r metrics.Registry) { // http.HandleFunc("/debug/vars", e.expHandler) // haven't found an elegant way, so just use a different endpoint http.Handle("/debug/metrics", h) + http.Handle("/debug/metrics/prometheus", prometheus.Handler(r)) } // ExpHandler will return an expvar powered metrics handler. diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go b/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go index 0fbfdb860..b6b2758b0 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/gauge.go @@ -6,6 +6,8 @@ import "sync/atomic" type Gauge interface { Snapshot() Gauge Update(int64) + Dec(int64) + Inc(int64) Value() int64 } @@ -65,6 +67,16 @@ func (GaugeSnapshot) Update(int64) { panic("Update called on a GaugeSnapshot") } +// Dec panics. +func (GaugeSnapshot) Dec(int64) { + panic("Dec called on a GaugeSnapshot") +} + +// Inc panics. +func (GaugeSnapshot) Inc(int64) { + panic("Inc called on a GaugeSnapshot") +} + // Value returns the value at the time the snapshot was taken. func (g GaugeSnapshot) Value() int64 { return int64(g) } @@ -77,6 +89,12 @@ func (NilGauge) Snapshot() Gauge { return NilGauge{} } // Update is a no-op. func (NilGauge) Update(v int64) {} +// Dec is a no-op. +func (NilGauge) Dec(i int64) {} + +// Inc is a no-op. +func (NilGauge) Inc(i int64) {} + // Value is a no-op. func (NilGauge) Value() int64 { return 0 } @@ -101,6 +119,16 @@ func (g *StandardGauge) Value() int64 { return atomic.LoadInt64(&g.value) } +// Dec decrements the gauge's current value by the given amount. +func (g *StandardGauge) Dec(i int64) { + atomic.AddInt64(&g.value, -i) +} + +// Inc increments the gauge's current value by the given amount. +func (g *StandardGauge) Inc(i int64) { + atomic.AddInt64(&g.value, i) +} + // FunctionalGauge returns value from given function type FunctionalGauge struct { value func() int64 @@ -118,3 +146,13 @@ func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } func (FunctionalGauge) Update(int64) { panic("Update called on a FunctionalGauge") } + +// Dec panics. +func (FunctionalGauge) Dec(int64) { + panic("Dec called on a FunctionalGauge") +} + +// Inc panics. +func (FunctionalGauge) Inc(int64) { + panic("Inc called on a FunctionalGauge") +} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go b/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go index 58f0dc765..a5a93af63 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/metrics.go @@ -16,34 +16,52 @@ import ( ) // Enabled is checked by the constructor functions for all of the -// standard metrics. If it is true, the metric returned is a stub. +// standard metrics. If it is true, the metric returned is a stub. // // This global kill-switch helps quantify the observer effect and makes // for less cluttered pprof profiles. -var Enabled bool = false +var Enabled = false + +// EnabledExpensive is a soft-flag meant for external packages to check if costly +// metrics gathering is allowed or not. The goal is to separate standard metrics +// for health monitoring and debug metrics that might impact runtime performance. +var EnabledExpensive = false // EnabledStr has the same function as Enabled but // it can be set during compilation (linking) time. var EnabledStr = "false" -// MetricsEnabledFlag is the CLI flag name to use to enable metrics collections. -const MetricsEnabledFlag = "metrics" -const DashboardEnabledFlag = "dashboard" +// enablerFlags is the CLI flag names to use to enable metrics collections. +var enablerFlags = []string{"metrics", "dashboard"} + +// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. +var expensiveEnablerFlags = []string{"metrics.expensive"} // Init enables or disables the metrics system. Since we need this to run before // any other code gets to create meters and timers, we'll actually do an ugly hack // and peek into the command line args for the metrics flag. func init() { for _, arg := range os.Args { - if flag := strings.TrimLeft(arg, "-"); flag == MetricsEnabledFlag || flag == DashboardEnabledFlag { - log.Info("Enabling metrics collection") - Enabled = true + flag := strings.TrimLeft(arg, "-") + + for _, enabler := range enablerFlags { + if !Enabled && flag == enabler { + log.Info("Enabling metrics collection") + Enabled = true + } + } + for _, enabler := range expensiveEnablerFlags { + if !EnabledExpensive && flag == enabler { + log.Info("Enabling expensive metrics collection") + EnabledExpensive = true + } } } if v, err := strconv.ParseBool(EnabledStr); err == nil && v { log.Info("Enabling metrics collection") - Enabled = v + Enabled = true + EnabledExpensive = true } } @@ -54,42 +72,56 @@ func CollectProcessMetrics(refresh time.Duration) { if !Enabled { return } + refreshFreq := int64(refresh / time.Second) + // Create the various data collectors + cpuStats := make([]*CPUStats, 2) memstats := make([]*runtime.MemStats, 2) diskstats := make([]*DiskStats, 2) for i := 0; i < len(memstats); i++ { + cpuStats[i] = new(CPUStats) memstats[i] = new(runtime.MemStats) diskstats[i] = new(DiskStats) } // Define the various metrics to collect - memAllocs := GetOrRegisterMeter("system/memory/allocs", DefaultRegistry) - memFrees := GetOrRegisterMeter("system/memory/frees", DefaultRegistry) - memInuse := GetOrRegisterMeter("system/memory/inuse", DefaultRegistry) - memPauses := GetOrRegisterMeter("system/memory/pauses", DefaultRegistry) - goroutines := GetOrRegisterGauge("system/goroutines", DefaultRegistry) + var ( + cpuSysLoad = GetOrRegisterGauge("system/cpu/sysload", DefaultRegistry) + cpuSysWait = GetOrRegisterGauge("system/cpu/syswait", DefaultRegistry) + cpuProcLoad = GetOrRegisterGauge("system/cpu/procload", DefaultRegistry) + cpuThreads = GetOrRegisterGauge("system/cpu/threads", DefaultRegistry) + cpuGoroutines = GetOrRegisterGauge("system/cpu/goroutines", DefaultRegistry) - var diskReads, diskReadBytes, diskWrites, diskWriteBytes Meter - var diskReadBytesCounter, diskWriteBytesCounter Counter - if err := ReadDiskStats(diskstats[0]); err == nil { - diskReads = GetOrRegisterMeter("system/disk/readcount", DefaultRegistry) - diskReadBytes = GetOrRegisterMeter("system/disk/readdata", DefaultRegistry) - diskReadBytesCounter = GetOrRegisterCounter("system/disk/readbytes", DefaultRegistry) - diskWrites = GetOrRegisterMeter("system/disk/writecount", DefaultRegistry) - diskWriteBytes = GetOrRegisterMeter("system/disk/writedata", DefaultRegistry) + memPauses = GetOrRegisterMeter("system/memory/pauses", DefaultRegistry) + memAllocs = GetOrRegisterMeter("system/memory/allocs", DefaultRegistry) + memFrees = GetOrRegisterMeter("system/memory/frees", DefaultRegistry) + memHeld = GetOrRegisterGauge("system/memory/held", DefaultRegistry) + memUsed = GetOrRegisterGauge("system/memory/used", DefaultRegistry) + + diskReads = GetOrRegisterMeter("system/disk/readcount", DefaultRegistry) + diskReadBytes = GetOrRegisterMeter("system/disk/readdata", DefaultRegistry) + diskReadBytesCounter = GetOrRegisterCounter("system/disk/readbytes", DefaultRegistry) + diskWrites = GetOrRegisterMeter("system/disk/writecount", DefaultRegistry) + diskWriteBytes = GetOrRegisterMeter("system/disk/writedata", DefaultRegistry) diskWriteBytesCounter = GetOrRegisterCounter("system/disk/writebytes", DefaultRegistry) - } else { - log.Debug("Failed to read disk metrics", "err", err) - } + ) // Iterate loading the different stats and updating the meters for i := 1; ; i++ { location1 := i % 2 location2 := (i - 1) % 2 + ReadCPUStats(cpuStats[location1]) + cpuSysLoad.Update((cpuStats[location1].GlobalTime - cpuStats[location2].GlobalTime) / refreshFreq) + cpuSysWait.Update((cpuStats[location1].GlobalWait - cpuStats[location2].GlobalWait) / refreshFreq) + cpuProcLoad.Update((cpuStats[location1].LocalTime - cpuStats[location2].LocalTime) / refreshFreq) + cpuThreads.Update(int64(threadCreateProfile.Count())) + cpuGoroutines.Update(int64(runtime.NumGoroutine())) + runtime.ReadMemStats(memstats[location1]) + memPauses.Mark(int64(memstats[location1].PauseTotalNs - memstats[location2].PauseTotalNs)) memAllocs.Mark(int64(memstats[location1].Mallocs - memstats[location2].Mallocs)) memFrees.Mark(int64(memstats[location1].Frees - memstats[location2].Frees)) - memInuse.Mark(int64(memstats[location1].Alloc - memstats[location2].Alloc)) - memPauses.Mark(int64(memstats[location1].PauseTotalNs - memstats[location2].PauseTotalNs)) + memHeld.Update(int64(memstats[location1].HeapSys - memstats[location1].HeapReleased)) + memUsed.Update(int64(memstats[location1].Alloc)) if ReadDiskStats(diskstats[location1]) == nil { diskReads.Mark(diskstats[location1].ReadCount - diskstats[location2].ReadCount) @@ -100,10 +132,6 @@ func CollectProcessMetrics(refresh time.Duration) { diskReadBytesCounter.Inc(diskstats[location1].ReadBytes - diskstats[location2].ReadBytes) diskWriteBytesCounter.Inc(diskstats[location1].WriteBytes - diskstats[location2].WriteBytes) } - - goroutines.Update(int64(runtime.NumGoroutine())) - time.Sleep(refresh) } - } diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go b/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go index df7f152ed..3fde55454 100644 --- a/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go +++ b/vendor/github.com/ethereum/go-ethereum/metrics/opentsdb.go @@ -10,7 +10,7 @@ import ( "time" ) -var shortHostName string = "" +var shortHostName = "" // OpenTSDBConfig provides a container with configuration parameters for // the OpenTSDB exporter diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/collector.go b/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/collector.go new file mode 100644 index 000000000..8350fa2aa --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/collector.go @@ -0,0 +1,115 @@ +// Copyright 2019 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 prometheus + +import ( + "bytes" + "fmt" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/metrics" +) + +var ( + typeGaugeTpl = "# TYPE %s gauge\n" + typeCounterTpl = "# TYPE %s counter\n" + typeSummaryTpl = "# TYPE %s summary\n" + keyValueTpl = "%s %v\n\n" + keyQuantileTagValueTpl = "%s {quantile=\"%s\"} %v\n\n" +) + +// collector is a collection of byte buffers that aggregate Prometheus reports +// for different metric types. +type collector struct { + buff *bytes.Buffer +} + +// newCollector createa a new Prometheus metric aggregator. +func newCollector() *collector { + return &collector{ + buff: &bytes.Buffer{}, + } +} + +func (c *collector) addCounter(name string, m metrics.Counter) { + c.writeGaugeCounter(name, m.Count()) +} + +func (c *collector) addGauge(name string, m metrics.Gauge) { + c.writeGaugeCounter(name, m.Value()) +} + +func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) { + c.writeGaugeCounter(name, m.Value()) +} + +func (c *collector) addHistogram(name string, m metrics.Histogram) { + pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} + ps := m.Percentiles(pv) + c.writeSummaryCounter(name, m.Count()) + for i := range pv { + c.writeSummaryPercentile(name, strconv.FormatFloat(pv[i], 'f', -1, 64), ps[i]) + } +} + +func (c *collector) addMeter(name string, m metrics.Meter) { + c.writeGaugeCounter(name, m.Count()) +} + +func (c *collector) addTimer(name string, m metrics.Timer) { + pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999} + ps := m.Percentiles(pv) + c.writeSummaryCounter(name, m.Count()) + for i := range pv { + c.writeSummaryPercentile(name, strconv.FormatFloat(pv[i], 'f', -1, 64), ps[i]) + } +} + +func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) { + if len(m.Values()) <= 0 { + return + } + ps := m.Percentiles([]float64{50, 95, 99}) + val := m.Values() + c.writeSummaryCounter(name, len(val)) + c.writeSummaryPercentile(name, "0.50", ps[0]) + c.writeSummaryPercentile(name, "0.95", ps[1]) + c.writeSummaryPercentile(name, "0.99", ps[2]) +} + +func (c *collector) writeGaugeCounter(name string, value interface{}) { + name = mutateKey(name) + c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name)) + c.buff.WriteString(fmt.Sprintf(keyValueTpl, name, value)) +} + +func (c *collector) writeSummaryCounter(name string, value interface{}) { + name = mutateKey(name + "_count") + c.buff.WriteString(fmt.Sprintf(typeCounterTpl, name)) + c.buff.WriteString(fmt.Sprintf(keyValueTpl, name, value)) +} + +func (c *collector) writeSummaryPercentile(name, p string, value interface{}) { + name = mutateKey(name) + c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, name)) + c.buff.WriteString(fmt.Sprintf(keyQuantileTagValueTpl, name, p, value)) +} + +func mutateKey(key string) string { + return strings.Replace(key, "/", "_", -1) +} diff --git a/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/prometheus.go b/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/prometheus.go new file mode 100644 index 000000000..9ad5ec7e9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/metrics/prometheus/prometheus.go @@ -0,0 +1,68 @@ +// Copyright 2019 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 prometheus exposes go-metrics into a Prometheus format. +package prometheus + +import ( + "fmt" + "net/http" + "sort" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" +) + +// Handler returns an HTTP handler which dump metrics in Prometheus format. +func Handler(reg metrics.Registry) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Gather and pre-sort the metrics to avoid random listings + var names []string + reg.Each(func(name string, i interface{}) { + names = append(names, name) + }) + sort.Strings(names) + + // Aggregate all the metris into a Prometheus collector + c := newCollector() + + for _, name := range names { + i := reg.Get(name) + + switch m := i.(type) { + case metrics.Counter: + c.addCounter(name, m.Snapshot()) + case metrics.Gauge: + c.addGauge(name, m.Snapshot()) + case metrics.GaugeFloat64: + c.addGaugeFloat64(name, m.Snapshot()) + case metrics.Histogram: + c.addHistogram(name, m.Snapshot()) + case metrics.Meter: + c.addMeter(name, m.Snapshot()) + case metrics.Timer: + c.addTimer(name, m.Snapshot()) + case metrics.ResettingTimer: + c.addResettingTimer(name, m.Snapshot()) + default: + log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i)) + } + } + w.Header().Add("Content-Type", "text/plain") + w.Header().Add("Content-Length", fmt.Sprint(c.buff.Len())) + w.Write(c.buff.Bytes()) + }) +} diff --git a/vendor/github.com/ethereum/go-ethereum/miner/miner.go b/vendor/github.com/ethereum/go-ethereum/miner/miner.go index 5218c1210..ab97b0c03 100644 --- a/vendor/github.com/ethereum/go-ethereum/miner/miner.go +++ b/vendor/github.com/ethereum/go-ethereum/miner/miner.go @@ -19,10 +19,12 @@ package miner import ( "fmt" + "math/big" "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -39,6 +41,18 @@ type Backend interface { TxPool() *core.TxPool } +// Config is the configuration parameters of mining. +type Config struct { + Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards (default = first account) + Notify []string `toml:",omitempty"` // HTTP URL list to be notified of new work packages(only useful in ethash). + ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner + GasFloor uint64 // Target gas floor for mined blocks. + GasCeil uint64 // Target gas ceiling for mined blocks. + GasPrice *big.Int // Minimum gas price for mining a transaction + Recommit time.Duration // The time interval for miner to re-create mining work. + Noverify bool // Disable remote mining solution verification(only useful in ethash). +} + // Miner creates blocks and searches for proof-of-work values. type Miner struct { mux *event.TypeMux @@ -52,13 +66,13 @@ type Miner struct { shouldStart int32 // should start indicates whether we should start after sync } -func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(block *types.Block) bool) *Miner { +func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(block *types.Block) bool) *Miner { miner := &Miner{ eth: eth, mux: mux, engine: engine, exitCh: make(chan struct{}), - worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil, isLocalBlock), + worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock), canStart: 1, } go miner.update() diff --git a/vendor/github.com/ethereum/go-ethereum/miner/stress_clique.go b/vendor/github.com/ethereum/go-ethereum/miner/stress_clique.go index 7e19975ae..7f5db2e52 100644 --- a/vendor/github.com/ethereum/go-ethereum/miner/stress_clique.go +++ b/vendor/github.com/ethereum/go-ethereum/miner/stress_clique.go @@ -69,7 +69,7 @@ func main() { if err != nil { panic(err) } - defer node.Stop() + defer node.Close() for node.Server().NodeInfo().Ports.Listener == 0 { time.Sleep(250 * time.Millisecond) @@ -199,10 +199,12 @@ func makeSealer(genesis *core.Genesis) (*node.Node, error) { DatabaseHandles: 256, TxPool: core.DefaultTxPoolConfig, GPO: eth.DefaultConfig.GPO, - MinerGasFloor: genesis.GasLimit * 9 / 10, - MinerGasCeil: genesis.GasLimit * 11 / 10, - MinerGasPrice: big.NewInt(1), - MinerRecommit: time.Second, + Miner: Config{ + GasFloor: genesis.GasLimit * 9 / 10, + GasCeil: genesis.GasLimit * 11 / 10, + GasPrice: big.NewInt(1), + Recommit: time.Second, + }, }) }); err != nil { return nil, err diff --git a/vendor/github.com/ethereum/go-ethereum/miner/stress_ethash.go b/vendor/github.com/ethereum/go-ethereum/miner/stress_ethash.go index 044ca9a21..7d4a7d24f 100644 --- a/vendor/github.com/ethereum/go-ethereum/miner/stress_ethash.go +++ b/vendor/github.com/ethereum/go-ethereum/miner/stress_ethash.go @@ -69,7 +69,7 @@ func main() { if err != nil { panic(err) } - defer node.Stop() + defer node.Close() for node.Server().NodeInfo().Ports.Listener == 0 { time.Sleep(250 * time.Millisecond) @@ -179,10 +179,12 @@ func makeMiner(genesis *core.Genesis) (*node.Node, error) { TxPool: core.DefaultTxPoolConfig, GPO: eth.DefaultConfig.GPO, Ethash: eth.DefaultConfig.Ethash, - MinerGasFloor: genesis.GasLimit * 9 / 10, - MinerGasCeil: genesis.GasLimit * 11 / 10, - MinerGasPrice: big.NewInt(1), - MinerRecommit: time.Second, + Miner: Config{ + GasFloor: genesis.GasLimit * 9 / 10, + GasCeil: genesis.GasLimit * 11 / 10, + GasPrice: big.NewInt(1), + Recommit: time.Second, + }, }) }); err != nil { return nil, err diff --git a/vendor/github.com/ethereum/go-ethereum/miner/worker.go b/vendor/github.com/ethereum/go-ethereum/miner/worker.go index 44a9f44f7..183499ec3 100644 --- a/vendor/github.com/ethereum/go-ethereum/miner/worker.go +++ b/vendor/github.com/ethereum/go-ethereum/miner/worker.go @@ -122,13 +122,11 @@ type intervalAdjust struct { // worker is the main object which takes care of submitting new work to consensus engine // and gathering the sealing result. type worker struct { - config *params.ChainConfig - engine consensus.Engine - eth Backend - chain *core.BlockChain - - gasFloor uint64 - gasCeil uint64 + config *Config + chainConfig *params.ChainConfig + engine consensus.Engine + eth Backend + chain *core.BlockChain // Subscriptions mux *event.TypeMux @@ -178,15 +176,14 @@ type worker struct { resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. } -func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(*types.Block) bool) *worker { +func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool) *worker { worker := &worker{ config: config, + chainConfig: chainConfig, engine: engine, eth: eth, mux: mux, chain: eth.BlockChain(), - gasFloor: gasFloor, - gasCeil: gasCeil, isLocalBlock: isLocalBlock, localUncles: make(map[common.Hash]*types.Block), remoteUncles: make(map[common.Hash]*types.Block), @@ -210,6 +207,7 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, worker.chainSideSub = eth.BlockChain().SubscribeChainSideEvent(worker.chainSideCh) // Sanitize recommit interval if the user-specified one is too short. + recommit := worker.config.Recommit if recommit < minRecommitInterval { log.Warn("Sanitizing miner recommit interval", "provided", recommit, "updated", minRecommitInterval) recommit = minRecommitInterval @@ -354,7 +352,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { case <-timer.C: // If mining is running resubmit a new work cycle periodically to pull in // higher priced transactions. Disable this overhead for pending blocks. - if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) { + if w.isRunning() && (w.chainConfig.Clique == nil || w.chainConfig.Clique.Period > 0) { // Short circuit if no new transaction arrives. if atomic.LoadInt32(&w.newTxs) == 0 { timer.Reset(recommit) @@ -455,6 +453,10 @@ func (w *worker) mainLoop() { // already included in the current mining block. These transactions will // be automatically eliminated. if !w.isRunning() && w.current != nil { + // If block is already full, abort + if gp := w.current.gasPool; gp != nil && gp.Gas() < params.TxGas { + continue + } w.mu.RLock() coinbase := w.coinbase w.mu.RUnlock() @@ -465,12 +467,18 @@ func (w *worker) mainLoop() { txs[acc] = append(txs[acc], tx) } txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs) + tcount := w.current.tcount w.commitTransactions(txset, coinbase, nil) - w.updateSnapshot() + // Only update the snapshot if any new transactons were added + // to the pending block + if tcount != w.current.tcount { + w.updateSnapshot() + } } else { - // If we're mining, but nothing is being processed, wake on new transactions - if w.config.Clique != nil && w.config.Clique.Period == 0 { - w.commitNewWork(nil, false, time.Now().Unix()) + // If clique is running in dev mode(period is 0), disable + // advance sealing here. + if w.chainConfig.Clique != nil && w.chainConfig.Clique.Period == 0 { + w.commitNewWork(nil, true, time.Now().Unix()) } } atomic.AddInt32(&w.newTxs, int32(len(ev.Txs))) @@ -566,6 +574,11 @@ func (w *worker) resultLoop() { logs []*types.Log ) for i, receipt := range task.receipts { + // add block location fields + receipt.BlockHash = hash + receipt.BlockNumber = block.Number() + receipt.TransactionIndex = uint(i) + receipts[i] = new(types.Receipt) *receipts[i] = *receipt // Update the block hash in all logs since it is now available and not when the @@ -613,7 +626,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { return err } env := &environment{ - signer: types.NewEIP155Signer(w.config.ChainID), + signer: types.NewEIP155Signer(w.chainConfig.ChainID), state: state, ancestors: mapset.NewSet(), family: mapset.NewSet(), @@ -691,7 +704,7 @@ func (w *worker) updateSnapshot() { func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() - receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) if err != nil { w.current.state.RevertToSnapshot(snap) return nil, err @@ -752,8 +765,8 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin from, _ := types.Sender(w.current.signer, tx) // Check whether the tx is replay protected. If we're not in the EIP155 hf // phase, start ignoring the sender until we do. - if tx.Protected() && !w.config.IsEIP155(w.current.header.Number) { - log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.config.EIP155Block) + if tx.Protected() && !w.chainConfig.IsEIP155(w.current.header.Number) { + log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.chainConfig.EIP155Block) txs.Pop() continue @@ -837,7 +850,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) header := &types.Header{ ParentHash: parent.Hash(), Number: num.Add(num, common.Big1), - GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil), + GasLimit: core.CalcGasLimit(parent, w.config.GasFloor, w.config.GasCeil), Extra: w.extra, Time: uint64(timestamp), } @@ -854,12 +867,12 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) return } // If we are care about TheDAO hard-fork check whether to override the extra-data or not - if daoBlock := w.config.DAOForkBlock; daoBlock != nil { + if daoBlock := w.chainConfig.DAOForkBlock; daoBlock != nil { // Check whether the block is among the fork extra-override range limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 { // Depending whether we support or oppose the fork, override differently - if w.config.DAOForkSupport { + if w.chainConfig.DAOForkSupport { header.Extra = common.CopyBytes(params.DAOForkBlockExtra) } else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) { header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data @@ -874,7 +887,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) } // Create the current work task and check any fork transitions needed env := w.current - if w.config.DAOForkSupport && w.config.DAOForkBlock != nil && w.config.DAOForkBlock.Cmp(header.Number) == 0 { + if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(env.state) } // Accumulate the uncles for the current block @@ -952,7 +965,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st *receipts[i] = *l } s := w.current.state.Copy() - block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) + block, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) if err != nil { return err } diff --git a/vendor/github.com/ethereum/go-ethereum/node/api.go b/vendor/github.com/ethereum/go-ethereum/node/api.go index bb1c01119..6f49f2cf9 100644 --- a/vendor/github.com/ethereum/go-ethereum/node/api.go +++ b/vendor/github.com/ethereum/go-ethereum/node/api.go @@ -20,11 +20,9 @@ import ( "context" "fmt" "strings" - "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rpc" @@ -51,7 +49,7 @@ func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) { return false, ErrNodeStopped } // Try to add the url as a static peer and return - node, err := enode.ParseV4(url) + node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { return false, fmt.Errorf("invalid enode: %v", err) } @@ -67,7 +65,7 @@ func (api *PrivateAdminAPI) RemovePeer(url string) (bool, error) { return false, ErrNodeStopped } // Try to remove the url as a static peer and return - node, err := enode.ParseV4(url) + node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { return false, fmt.Errorf("invalid enode: %v", err) } @@ -100,7 +98,7 @@ func (api *PrivateAdminAPI) AddTrustedPeer(url string) (bool, error) { if server == nil { return false, ErrNodeStopped } - node, err := enode.ParseV4(url) + node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { return false, fmt.Errorf("invalid enode: %v", err) } @@ -116,7 +114,7 @@ func (api *PrivateAdminAPI) RemoveTrustedPeer(url string) (bool, error) { if server == nil { return false, ErrNodeStopped } - node, err := enode.ParseV4(url) + node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { return false, fmt.Errorf("invalid enode: %v", err) } @@ -315,161 +313,6 @@ func (api *PublicAdminAPI) Datadir() string { return api.node.DataDir() } -// PublicDebugAPI is the collection of debugging related API methods exposed over -// both secure and unsecure RPC channels. -type PublicDebugAPI struct { - node *Node // Node interfaced by this API -} - -// NewPublicDebugAPI creates a new API definition for the public debug methods -// of the node itself. -func NewPublicDebugAPI(node *Node) *PublicDebugAPI { - return &PublicDebugAPI{node: node} -} - -// Metrics retrieves all the known system metric collected by the node. -func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) { - // Create a rate formatter - units := []string{"", "K", "M", "G", "T", "E", "P"} - round := func(value float64, prec int) string { - unit := 0 - for value >= 1000 { - unit, value, prec = unit+1, value/1000, 2 - } - return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value) - } - format := func(total float64, rate float64) string { - return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2)) - } - // Iterate over all the metrics, and just dump for now - counters := make(map[string]interface{}) - metrics.DefaultRegistry.Each(func(name string, metric interface{}) { - // Create or retrieve the counter hierarchy for this metric - root, parts := counters, strings.Split(name, "/") - for _, part := range parts[:len(parts)-1] { - if _, ok := root[part]; !ok { - root[part] = make(map[string]interface{}) - } - root = root[part].(map[string]interface{}) - } - name = parts[len(parts)-1] - - // Fill the counter with the metric details, formatting if requested - if raw { - switch metric := metric.(type) { - case metrics.Counter: - root[name] = map[string]interface{}{ - "Overall": float64(metric.Count()), - } - - case metrics.Gauge: - root[name] = map[string]interface{}{ - "Value": float64(metric.Value()), - } - - case metrics.Meter: - root[name] = map[string]interface{}{ - "AvgRate01Min": metric.Rate1(), - "AvgRate05Min": metric.Rate5(), - "AvgRate15Min": metric.Rate15(), - "MeanRate": metric.RateMean(), - "Overall": float64(metric.Count()), - } - - case metrics.Timer: - root[name] = map[string]interface{}{ - "AvgRate01Min": metric.Rate1(), - "AvgRate05Min": metric.Rate5(), - "AvgRate15Min": metric.Rate15(), - "MeanRate": metric.RateMean(), - "Overall": float64(metric.Count()), - "Percentiles": map[string]interface{}{ - "5": metric.Percentile(0.05), - "20": metric.Percentile(0.2), - "50": metric.Percentile(0.5), - "80": metric.Percentile(0.8), - "95": metric.Percentile(0.95), - }, - } - - case metrics.ResettingTimer: - t := metric.Snapshot() - ps := t.Percentiles([]float64{5, 20, 50, 80, 95}) - root[name] = map[string]interface{}{ - "Measurements": len(t.Values()), - "Mean": t.Mean(), - "Percentiles": map[string]interface{}{ - "5": ps[0], - "20": ps[1], - "50": ps[2], - "80": ps[3], - "95": ps[4], - }, - } - - default: - root[name] = "Unknown metric type" - } - } else { - switch metric := metric.(type) { - case metrics.Counter: - root[name] = map[string]interface{}{ - "Overall": float64(metric.Count()), - } - - case metrics.Gauge: - root[name] = map[string]interface{}{ - "Value": float64(metric.Value()), - } - - case metrics.Meter: - root[name] = map[string]interface{}{ - "Avg01Min": format(metric.Rate1()*60, metric.Rate1()), - "Avg05Min": format(metric.Rate5()*300, metric.Rate5()), - "Avg15Min": format(metric.Rate15()*900, metric.Rate15()), - "Overall": format(float64(metric.Count()), metric.RateMean()), - } - - case metrics.Timer: - root[name] = map[string]interface{}{ - "Avg01Min": format(metric.Rate1()*60, metric.Rate1()), - "Avg05Min": format(metric.Rate5()*300, metric.Rate5()), - "Avg15Min": format(metric.Rate15()*900, metric.Rate15()), - "Overall": format(float64(metric.Count()), metric.RateMean()), - "Maximum": time.Duration(metric.Max()).String(), - "Minimum": time.Duration(metric.Min()).String(), - "Percentiles": map[string]interface{}{ - "5": time.Duration(metric.Percentile(0.05)).String(), - "20": time.Duration(metric.Percentile(0.2)).String(), - "50": time.Duration(metric.Percentile(0.5)).String(), - "80": time.Duration(metric.Percentile(0.8)).String(), - "95": time.Duration(metric.Percentile(0.95)).String(), - }, - } - - case metrics.ResettingTimer: - t := metric.Snapshot() - ps := t.Percentiles([]float64{5, 20, 50, 80, 95}) - root[name] = map[string]interface{}{ - "Measurements": len(t.Values()), - "Mean": time.Duration(t.Mean()).String(), - "Percentiles": map[string]interface{}{ - "5": time.Duration(ps[0]).String(), - "20": time.Duration(ps[1]).String(), - "50": time.Duration(ps[2]).String(), - "80": time.Duration(ps[3]).String(), - "95": time.Duration(ps[4]).String(), - }, - } - - default: - root[name] = "Unknown metric type" - } - } - }) - return counters, nil -} - // PublicWeb3API offers helper utils type PublicWeb3API struct { stack *Node diff --git a/vendor/github.com/ethereum/go-ethereum/node/config.go b/vendor/github.com/ethereum/go-ethereum/node/config.go index 7b32a5908..1905ac7fa 100644 --- a/vendor/github.com/ethereum/go-ethereum/node/config.go +++ b/vendor/github.com/ethereum/go-ethereum/node/config.go @@ -27,7 +27,9 @@ import ( "sync" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/external" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -80,13 +82,22 @@ type Config struct { // is created by New and destroyed when the node is stopped. KeyStoreDir string `toml:",omitempty"` + // ExternalSigner specifies an external URI for a clef-type signer + ExternalSigner string `toml:"omitempty"` + // UseLightweightKDF lowers the memory and CPU requirements of the key store // scrypt KDF at the expense of security. UseLightweightKDF bool `toml:",omitempty"` + // InsecureUnlockAllowed allows user to unlock accounts in unsafe http environment. + InsecureUnlockAllowed bool `toml:",omitempty"` + // NoUSB disables hardware wallet monitoring and connectivity. NoUSB bool `toml:",omitempty"` + // SmartCardDaemonPath is the path to the smartcard daemon's socket + SmartCardDaemonPath string `toml:",omitempty"` + // IPCPath is the requested location to place the IPC endpoint. If the path is // a simple file name, it is placed inside the data directory (or on the root // pipe path on Windows), whereas if it's a resolvable path name (absolute or @@ -151,6 +162,29 @@ type Config struct { // private APIs to untrusted users is a major security risk. WSExposeAll bool `toml:",omitempty"` + // GraphQLHost is the host interface on which to start the GraphQL server. If this + // field is empty, no GraphQL API endpoint will be started. + GraphQLHost string `toml:",omitempty"` + + // GraphQLPort is the TCP port number on which to start the GraphQL server. The + // default zero value is/ valid and will pick a port number randomly (useful + // for ephemeral nodes). + GraphQLPort int `toml:",omitempty"` + + // GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting + // clients. Please be aware that CORS is a browser enforced security, it's fully + // useless for custom HTTP clients. + GraphQLCors []string `toml:",omitempty"` + + // GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests. + // This is by default {'localhost'}. Using this prevents attacks like + // DNS rebinding, which bypasses SOP by simply masquerading as being within the same + // origin. These attacks do not utilize CORS, since they are not cross-domain. + // By explicitly checking the Host-header, the server will not allow requests + // made against the server with a malicious host domain. + // Requests using ip address directly are not affected + GraphQLVirtualHosts []string `toml:",omitempty"` + // Logger is a custom logger to use with the p2p.Server. Logger log.Logger `toml:",omitempty"` @@ -213,6 +247,15 @@ func (c *Config) HTTPEndpoint() string { return fmt.Sprintf("%s:%d", c.HTTPHost, c.HTTPPort) } +// GraphQLEndpoint resolves a GraphQL endpoint based on the configured host interface +// and port parameters. +func (c *Config) GraphQLEndpoint() string { + if c.GraphQLHost == "" { + return "" + } + return fmt.Sprintf("%s:%d", c.GraphQLHost, c.GraphQLPort) +} + // DefaultHTTPEndpoint returns the HTTP endpoint used by default. func DefaultHTTPEndpoint() string { config := &Config{HTTPHost: DefaultHTTPHost, HTTPPort: DefaultHTTPPort} @@ -234,6 +277,12 @@ func DefaultWSEndpoint() string { return config.WSEndpoint() } +// ExtRPCEnabled returns the indicator whether node enables the external +// RPC(http, ws or graphql). +func (c *Config) ExtRPCEnabled() bool { + return c.HTTPHost != "" || c.WSHost != "" || c.GraphQLHost != "" +} + // NodeName returns the devp2p node identifier. func (c *Config) NodeName() string { name := c.name() @@ -376,7 +425,7 @@ func (c *Config) parsePersistentNodes(w *bool, path string) []*enode.Node { if url == "" { continue } - node, err := enode.ParseV4(url) + node, err := enode.Parse(enode.ValidSchemes, url) if err != nil { log.Error(fmt.Sprintf("Node URL %s: %v\n", url, err)) continue @@ -430,24 +479,52 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) { return nil, "", err } // Assemble the account manager and supported backends - backends := []accounts.Backend{ - keystore.NewKeyStore(keydir, scryptN, scryptP), - } - if !conf.NoUSB { - // Start a USB hub for Ledger hardware wallets - if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil { - log.Warn(fmt.Sprintf("Failed to start Ledger hub, disabling: %v", err)) + var backends []accounts.Backend + if len(conf.ExternalSigner) > 0 { + log.Info("Using external signer", "url", conf.ExternalSigner) + if extapi, err := external.NewExternalBackend(conf.ExternalSigner); err == nil { + backends = append(backends, extapi) } else { - backends = append(backends, ledgerhub) - } - // Start a USB hub for Trezor hardware wallets - if trezorhub, err := usbwallet.NewTrezorHub(); err != nil { - log.Warn(fmt.Sprintf("Failed to start Trezor hub, disabling: %v", err)) - } else { - backends = append(backends, trezorhub) + return nil, "", fmt.Errorf("error connecting to external signer: %v", err) } } - return accounts.NewManager(backends...), ephemeral, nil + if len(backends) == 0 { + // For now, we're using EITHER external signer OR local signers. + // If/when we implement some form of lockfile for USB and keystore wallets, + // we can have both, but it's very confusing for the user to see the same + // accounts in both externally and locally, plus very racey. + backends = append(backends, keystore.NewKeyStore(keydir, scryptN, scryptP)) + if !conf.NoUSB { + // Start a USB hub for Ledger hardware wallets + if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil { + log.Warn(fmt.Sprintf("Failed to start Ledger hub, disabling: %v", err)) + } else { + backends = append(backends, ledgerhub) + } + // Start a USB hub for Trezor hardware wallets (HID version) + if trezorhub, err := usbwallet.NewTrezorHubWithHID(); err != nil { + log.Warn(fmt.Sprintf("Failed to start HID Trezor hub, disabling: %v", err)) + } else { + backends = append(backends, trezorhub) + } + // Start a USB hub for Trezor hardware wallets (WebUSB version) + if trezorhub, err := usbwallet.NewTrezorHubWithWebUSB(); err != nil { + log.Warn(fmt.Sprintf("Failed to start WebUSB Trezor hub, disabling: %v", err)) + } else { + backends = append(backends, trezorhub) + } + } + if len(conf.SmartCardDaemonPath) > 0 { + // Start a smart card hub + if schub, err := scwallet.NewHub(conf.SmartCardDaemonPath, scwallet.Scheme, keydir); err != nil { + log.Warn(fmt.Sprintf("Failed to start smart card hub, disabling: %v", err)) + } else { + backends = append(backends, schub) + } + } + } + + return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), ephemeral, nil } var warnLock sync.Mutex diff --git a/vendor/github.com/ethereum/go-ethereum/node/defaults.go b/vendor/github.com/ethereum/go-ethereum/node/defaults.go index c1376dba0..f84a5d547 100644 --- a/vendor/github.com/ethereum/go-ethereum/node/defaults.go +++ b/vendor/github.com/ethereum/go-ethereum/node/defaults.go @@ -28,24 +28,28 @@ import ( ) const ( - DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server - DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server - DefaultWSHost = "localhost" // Default host interface for the websocket RPC server - DefaultWSPort = 8546 // Default TCP port for the websocket RPC server + DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server + DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server + DefaultWSHost = "localhost" // Default host interface for the websocket RPC server + DefaultWSPort = 8546 // Default TCP port for the websocket RPC server + DefaultGraphQLHost = "localhost" // Default host interface for the GraphQL server + DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server ) // DefaultConfig contains reasonable default settings. var DefaultConfig = Config{ - DataDir: DefaultDataDir(), - HTTPPort: DefaultHTTPPort, - HTTPModules: []string{"net", "web3"}, - HTTPVirtualHosts: []string{"localhost"}, - HTTPTimeouts: rpc.DefaultHTTPTimeouts, - WSPort: DefaultWSPort, - WSModules: []string{"net", "web3"}, + DataDir: DefaultDataDir(), + HTTPPort: DefaultHTTPPort, + HTTPModules: []string{"net", "web3"}, + HTTPVirtualHosts: []string{"localhost"}, + HTTPTimeouts: rpc.DefaultHTTPTimeouts, + WSPort: DefaultWSPort, + WSModules: []string{"net", "web3"}, + GraphQLPort: DefaultGraphQLPort, + GraphQLVirtualHosts: []string{"localhost"}, P2P: p2p.Config{ ListenAddr: ":30303", - MaxPeers: 25, + MaxPeers: 50, NAT: nat.Any(), }, } @@ -56,11 +60,20 @@ func DefaultDataDir() string { // Try to place the data folder in the user's home dir home := homeDir() if home != "" { - if runtime.GOOS == "darwin" { + switch runtime.GOOS { + case "darwin": return filepath.Join(home, "Library", "Ethereum") - } else if runtime.GOOS == "windows" { - return filepath.Join(home, "AppData", "Roaming", "Ethereum") - } else { + case "windows": + // We used to put everything in %HOME%\AppData\Roaming, but this caused + // problems with non-typical setups. If this fallback location exists and + // is non-empty, use it, otherwise DTRT and check %LOCALAPPDATA%. + fallback := filepath.Join(home, "AppData", "Roaming", "Ethereum") + appdata := windowsAppData() + if appdata == "" || isNonEmptyDir(fallback) { + return fallback + } + return filepath.Join(appdata, "Ethereum") + default: return filepath.Join(home, ".ethereum") } } @@ -68,6 +81,27 @@ func DefaultDataDir() string { return "" } +func windowsAppData() string { + v := os.Getenv("LOCALAPPDATA") + if v == "" { + // Windows XP and below don't have LocalAppData. Crash here because + // we don't support Windows XP and undefining the variable will cause + // other issues. + panic("environment variable LocalAppData is undefined") + } + return v +} + +func isNonEmptyDir(dir string) bool { + f, err := os.Open(dir) + if err != nil { + return false + } + names, _ := f.Readdir(1) + f.Close() + return len(names) > 0 +} + func homeDir() string { if home := os.Getenv("HOME"); home != "" { return home diff --git a/vendor/github.com/ethereum/go-ethereum/node/node.go b/vendor/github.com/ethereum/go-ethereum/node/node.go index 6a6474928..6ec7edd5e 100644 --- a/vendor/github.com/ethereum/go-ethereum/node/node.go +++ b/vendor/github.com/ethereum/go-ethereum/node/node.go @@ -27,13 +27,14 @@ import ( "sync" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" - "github.com/prometheus/prometheus/util/flock" + "github.com/prometheus/tsdb/fileutil" ) // Node is a container on which services can be registered. @@ -42,8 +43,8 @@ type Node struct { config *Config accman *accounts.Manager - ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop - instanceDirLock flock.Releaser // prevents concurrent use of instance directory + ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop + instanceDirLock fileutil.Releaser // prevents concurrent use of instance directory serverConfig p2p.Config server *p2p.Server // Currently running P2P networking layer @@ -122,6 +123,29 @@ func New(conf *Config) (*Node, error) { }, nil } +// Close stops the Node and releases resources acquired in +// Node constructor New. +func (n *Node) Close() error { + var errs []error + + // Terminate all subsystems and collect any errors + if err := n.Stop(); err != nil && err != ErrNodeStopped { + errs = append(errs, err) + } + if err := n.accman.Close(); err != nil { + errs = append(errs, err) + } + // Report any errors that might have occurred + switch len(errs) { + case 0: + return nil + case 1: + return errs[0] + default: + return fmt.Errorf("%v", errs) + } +} + // Register injects a new service into the node's stack. The service created by // the passed constructor must be unique in its type with regard to sibling ones. func (n *Node) Register(constructor ServiceConstructor) error { @@ -198,7 +222,7 @@ func (n *Node) Start() error { return convertFileLockError(err) } // Start each of the services - started := []reflect.Type{} + var started []reflect.Type for kind, service := range services { // Start the next service, stopping all previous upon failure if err := service.Start(running); err != nil { @@ -224,10 +248,14 @@ func (n *Node) Start() error { n.services = services n.server = running n.stop = make(chan struct{}) - return nil } +// Config returns the configuration of node. +func (n *Node) Config() *Config { + return n.config +} + func (n *Node) openDataDir() error { if n.config.DataDir == "" { return nil // ephemeral @@ -239,7 +267,7 @@ func (n *Node) openDataDir() error { } // Lock the instance directory to prevent concurrent use by another instance as well as // accidental use of the instance directory as a database. - release, _, err := flock.New(filepath.Join(instdir, "LOCK")) + release, _, err := fileutil.Flock(filepath.Join(instdir, "LOCK")) if err != nil { return convertFileLockError(err) } @@ -628,11 +656,31 @@ func (n *Node) EventMux() *event.TypeMux { // OpenDatabase opens an existing database with the given name (or creates one if no // previous can be found) from within the node's instance directory. If the node is // ephemeral, a memory database is returned. -func (n *Node) OpenDatabase(name string, cache, handles int) (ethdb.Database, error) { +func (n *Node) OpenDatabase(name string, cache, handles int, namespace string) (ethdb.Database, error) { if n.config.DataDir == "" { - return ethdb.NewMemDatabase(), nil + return rawdb.NewMemoryDatabase(), nil } - return ethdb.NewLDBDatabase(n.config.ResolvePath(name), cache, handles) + return rawdb.NewLevelDBDatabase(n.config.ResolvePath(name), cache, handles, namespace) +} + +// OpenDatabaseWithFreezer opens an existing database with the given name (or +// creates one if no previous can be found) from within the node's data directory, +// also attaching a chain freezer to it that moves ancient chain data from the +// database to immutable append-only files. If the node is an ephemeral one, a +// memory database is returned. +func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string) (ethdb.Database, error) { + if n.config.DataDir == "" { + return rawdb.NewMemoryDatabase(), nil + } + root := n.config.ResolvePath(name) + + switch { + case freezer == "": + freezer = filepath.Join(root, "ancient") + case !filepath.IsAbs(freezer): + freezer = n.config.ResolvePath(freezer) + } + return rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace) } // ResolvePath returns the absolute path of a resource in the instance directory. @@ -656,11 +704,6 @@ func (n *Node) apis() []rpc.API { Namespace: "debug", Version: "1.0", Service: debug.Handler, - }, { - Namespace: "debug", - Version: "1.0", - Service: NewPublicDebugAPI(n), - Public: true, }, { Namespace: "web3", Version: "1.0", diff --git a/vendor/github.com/ethereum/go-ethereum/node/service.go b/vendor/github.com/ethereum/go-ethereum/node/service.go index 6a96d9b1e..4dea00995 100644 --- a/vendor/github.com/ethereum/go-ethereum/node/service.go +++ b/vendor/github.com/ethereum/go-ethereum/node/service.go @@ -17,9 +17,11 @@ package node import ( + "path/filepath" "reflect" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" @@ -39,15 +41,31 @@ type ServiceContext struct { // OpenDatabase opens an existing database with the given name (or creates one // if no previous can be found) from within the node's data directory. If the // node is an ephemeral one, a memory database is returned. -func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int) (ethdb.Database, error) { +func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int, namespace string) (ethdb.Database, error) { if ctx.config.DataDir == "" { - return ethdb.NewMemDatabase(), nil + return rawdb.NewMemoryDatabase(), nil } - db, err := ethdb.NewLDBDatabase(ctx.config.ResolvePath(name), cache, handles) - if err != nil { - return nil, err + return rawdb.NewLevelDBDatabase(ctx.config.ResolvePath(name), cache, handles, namespace) +} + +// OpenDatabaseWithFreezer opens an existing database with the given name (or +// creates one if no previous can be found) from within the node's data directory, +// also attaching a chain freezer to it that moves ancient chain data from the +// database to immutable append-only files. If the node is an ephemeral one, a +// memory database is returned. +func (ctx *ServiceContext) OpenDatabaseWithFreezer(name string, cache int, handles int, freezer string, namespace string) (ethdb.Database, error) { + if ctx.config.DataDir == "" { + return rawdb.NewMemoryDatabase(), nil } - return db, nil + root := ctx.config.ResolvePath(name) + + switch { + case freezer == "": + freezer = filepath.Join(root, "ancient") + case !filepath.IsAbs(freezer): + freezer = ctx.config.ResolvePath(freezer) + } + return rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace) } // ResolvePath resolves a user path into the data directory if that was relative @@ -67,6 +85,12 @@ func (ctx *ServiceContext) Service(service interface{}) error { return ErrServiceUnknown } +// ExtRPCEnabled returns the indicator whether node enables the external +// RPC(http, ws or graphql). +func (ctx *ServiceContext) ExtRPCEnabled() bool { + return ctx.config.ExtRPCEnabled() +} + // ServiceConstructor is the function signature of the constructors needed to be // registered for service instantiation. type ServiceConstructor func(ctx *ServiceContext) (Service, error) diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go index bdaa11a95..8dee5063f 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go @@ -17,7 +17,6 @@ package p2p import ( - "container/heap" "errors" "fmt" "net" @@ -29,9 +28,10 @@ import ( ) const ( - // This is the amount of time spent waiting in between - // redialing a certain node. - dialHistoryExpiration = 30 * time.Second + // This is the amount of time spent waiting in between redialing a certain node. The + // limit is a bit higher than inboundThrottleTime to prevent failing dials in small + // private networks. + dialHistoryExpiration = inboundThrottleTime + 5*time.Second // Discovery lookups are throttled and can only run // once every few seconds. @@ -65,23 +65,23 @@ func (t TCPDialer) Dial(dest *enode.Node) (net.Conn, error) { } // dialstate schedules dials and discovery lookups. -// it get's a chance to compute new tasks on every iteration +// It gets a chance to compute new tasks on every iteration // of the main loop in Server.run. type dialstate struct { maxDynDials int ntab discoverTable netrestrict *netutil.Netlist self enode.ID + bootnodes []*enode.Node // default dials when there are no peers + log log.Logger + start time.Time // time when the dialer was first used lookupRunning bool dialing map[enode.ID]connFlag lookupBuf []*enode.Node // current discovery lookup results randomNodes []*enode.Node // filled from Table static map[enode.ID]*dialTask - hist *dialHistory - - start time.Time // time when the dialer was first used - bootnodes []*enode.Node // default dials when there are no peers + hist expHeap } type discoverTable interface { @@ -91,15 +91,6 @@ type discoverTable interface { ReadRandomNodes([]*enode.Node) int } -// the dial history remembers recent dials. -type dialHistory []pastDial - -// pastDial is an entry in the dial history. -type pastDial struct { - id enode.ID - exp time.Time -} - type task interface { Do(*Server) } @@ -126,20 +117,23 @@ type waitExpireTask struct { time.Duration } -func newDialState(self enode.ID, static []*enode.Node, bootnodes []*enode.Node, ntab discoverTable, maxdyn int, netrestrict *netutil.Netlist) *dialstate { +func newDialState(self enode.ID, ntab discoverTable, maxdyn int, cfg *Config) *dialstate { s := &dialstate{ maxDynDials: maxdyn, ntab: ntab, self: self, - netrestrict: netrestrict, + netrestrict: cfg.NetRestrict, + log: cfg.Logger, static: make(map[enode.ID]*dialTask), dialing: make(map[enode.ID]connFlag), - bootnodes: make([]*enode.Node, len(bootnodes)), + bootnodes: make([]*enode.Node, len(cfg.BootstrapNodes)), randomNodes: make([]*enode.Node, maxdyn/2), - hist: new(dialHistory), } - copy(s.bootnodes, bootnodes) - for _, n := range static { + copy(s.bootnodes, cfg.BootstrapNodes) + if s.log == nil { + s.log = log.Root() + } + for _, n := range cfg.StaticNodes { s.addStatic(n) } return s @@ -154,9 +148,6 @@ func (s *dialstate) addStatic(n *enode.Node) { func (s *dialstate) removeStatic(n *enode.Node) { // This removes a task so future attempts to connect will not be made. delete(s.static, n.ID()) - // This removes a previous dial timestamp so that application - // can force a server to reconnect with chosen peer immediately. - s.hist.remove(n.ID()) } func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Time) []task { @@ -167,7 +158,7 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti var newtasks []task addDial := func(flag connFlag, n *enode.Node) bool { if err := s.checkDial(n, peers); err != nil { - log.Trace("Skipping dial candidate", "id", n.ID(), "addr", &net.TCPAddr{IP: n.IP(), Port: n.TCP()}, "err", err) + s.log.Trace("Skipping dial candidate", "id", n.ID(), "addr", &net.TCPAddr{IP: n.IP(), Port: n.TCP()}, "err", err) return false } s.dialing[n.ID()] = flag @@ -196,11 +187,8 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti err := s.checkDial(t.dest, peers) switch err { case errNotWhitelisted, errSelf: - log.Warn("Removing static dial candidate", "id", t.dest.ID, "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}, "err", err) + s.log.Warn("Removing static dial candidate", "id", t.dest.ID, "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}, "err", err) delete(s.static, t.dest.ID()) - case errRecentlyDialed: - expiry := s.hist.expiry(t.dest.ID()) - log.Debug("peer was recently dialed", "enode", t.dest.String(), "expires at", expiry, "after", expiry.Sub(time.Now())) case nil: s.dialing[id] = t.flags newtasks = append(newtasks, t) @@ -249,7 +237,7 @@ func (s *dialstate) newTasks(nRunning int, peers map[enode.ID]*Peer, now time.Ti // This should prevent cases where the dialer logic is not ticked // because there are no pending events. if nRunning == 0 && len(newtasks) == 0 && s.hist.Len() > 0 { - t := &waitExpireTask{s.hist.min().exp.Sub(now)} + t := &waitExpireTask{s.hist.nextExpiry().Sub(now)} newtasks = append(newtasks, t) } return newtasks @@ -274,7 +262,7 @@ func (s *dialstate) checkDial(n *enode.Node, peers map[enode.ID]*Peer) error { return errSelf case s.netrestrict != nil && !s.netrestrict.Contains(n.IP()): return errNotWhitelisted - case s.hist.contains(n.ID()): + case s.hist.contains(string(n.ID().Bytes())): return errRecentlyDialed } return nil @@ -283,7 +271,7 @@ func (s *dialstate) checkDial(n *enode.Node, peers map[enode.ID]*Peer) error { func (s *dialstate) taskDone(t task, now time.Time) { switch t := t.(type) { case *dialTask: - s.hist.add(t.dest.ID(), now.Add(dialHistoryExpiration)) + s.hist.add(string(t.dest.ID().Bytes()), now.Add(dialHistoryExpiration)) delete(s.dialing, t.dest.ID()) case *discoverTask: s.lookupRunning = false @@ -299,7 +287,7 @@ func (t *dialTask) Do(srv *Server) { } err := t.dial(srv, t.dest) if err != nil { - log.Trace("Dial error", "task", t, "err", err) + srv.log.Trace("Dial error", "task", t, "err", err) // Try resolving the ID of static nodes if dialing failed. if _, ok := err.(*dialError); ok && t.flags&staticDialedConn != 0 { if t.resolve(srv) { @@ -317,7 +305,7 @@ func (t *dialTask) Do(srv *Server) { // The backoff delay resets when the node is found. func (t *dialTask) resolve(srv *Server) bool { if srv.ntab == nil { - log.Debug("Can't resolve node", "id", t.dest.ID, "err", "discovery is disabled") + srv.log.Debug("Can't resolve node", "id", t.dest.ID, "err", "discovery is disabled") return false } if t.resolveDelay == 0 { @@ -333,13 +321,13 @@ func (t *dialTask) resolve(srv *Server) bool { if t.resolveDelay > maxResolveDelay { t.resolveDelay = maxResolveDelay } - log.Debug("Resolving node failed", "id", t.dest.ID, "newdelay", t.resolveDelay) + srv.log.Debug("Resolving node failed", "id", t.dest.ID, "newdelay", t.resolveDelay) return false } // The node was found. t.resolveDelay = initialResolveDelay t.dest = resolved - log.Debug("Resolved node", "id", t.dest.ID, "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) + srv.log.Debug("Resolved node", "id", t.dest.ID, "addr", &net.TCPAddr{IP: t.dest.IP(), Port: t.dest.TCP()}) return true } @@ -388,59 +376,3 @@ func (t waitExpireTask) Do(*Server) { func (t waitExpireTask) String() string { return fmt.Sprintf("wait for dial hist expire (%v)", t.Duration) } - -// Use only these methods to access or modify dialHistory. -func (h dialHistory) min() pastDial { - return h[0] -} -func (h *dialHistory) add(id enode.ID, exp time.Time) { - heap.Push(h, pastDial{id, exp}) - -} -func (h *dialHistory) remove(id enode.ID) bool { - for i, v := range *h { - if v.id == id { - heap.Remove(h, i) - return true - } - } - return false -} -func (h dialHistory) contains(id enode.ID) bool { - for _, v := range h { - if v.id == id { - return true - } - } - return false -} - -func (h dialHistory) expiry(id enode.ID) time.Time { - for _, v := range h { - if v.id == id { - return v.exp - } - } - return time.Time{} -} - -func (h *dialHistory) expire(now time.Time) { - for h.Len() > 0 && h.min().exp.Before(now) { - heap.Pop(h) - } -} - -// heap.Interface boilerplate -func (h dialHistory) Len() int { return len(h) } -func (h dialHistory) Less(i, j int) bool { return h[i].exp.Before(h[j].exp) } -func (h dialHistory) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *dialHistory) Push(x interface{}) { - *h = append(*h, x.(pastDial)) -} -func (h *dialHistory) Pop() interface{} { - old := *h - n := len(old) - x := old[n-1] - *h = old[0 : n-1] - return x -} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go new file mode 100644 index 000000000..3c080359f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/common.go @@ -0,0 +1,57 @@ +// Copyright 2019 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 discover + +import ( + "crypto/ecdsa" + "net" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/netutil" +) + +type UDPConn interface { + ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) + WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) + Close() error + LocalAddr() net.Addr +} + +// Config holds Table-related settings. +type Config struct { + // These settings are required and configure the UDP listener: + PrivateKey *ecdsa.PrivateKey + + // These settings are optional: + NetRestrict *netutil.Netlist // network whitelist + Bootnodes []*enode.Node // list of bootstrap nodes + Unhandled chan<- ReadPacket // unhandled packets are sent on this channel + Log log.Logger // if set, log messages go here +} + +// ListenUDP starts listening for discovery packets on the given UDP socket. +func ListenUDP(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { + return ListenV4(c, ln, cfg) +} + +// ReadPacket is a packet that couldn't be handled. Those packets are sent to the unhandled +// channel if configured. +type ReadPacket struct { + Data []byte + Addr *net.UDPAddr +} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/node.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/node.go index 8d4af166b..a7d9ce736 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discover/node.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/node.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/p2p/enode" ) @@ -64,7 +63,7 @@ func (e encPubkey) id() enode.ID { // recoverNodeKey computes the public key used to sign the // given hash from the signature. func recoverNodeKey(hash, sig []byte) (key encPubkey, err error) { - pubkey, err := secp256k1.RecoverPubkey(hash, sig) + pubkey, err := crypto.Ecrecover(hash, sig) if err != nil { return key, err } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/table.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/table.go index 3e9353753..e5a5793e3 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discover/table.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/table.go @@ -23,7 +23,6 @@ package discover import ( - "crypto/ecdsa" crand "crypto/rand" "encoding/binary" "fmt" @@ -34,7 +33,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/netutil" @@ -55,15 +53,17 @@ const ( bucketIPLimit, bucketSubnet = 2, 24 // at most 2 addresses from the same /24 tableIPLimit, tableSubnet = 10, 24 - maxFindnodeFailures = 5 // Nodes exceeding this limit are dropped - refreshInterval = 30 * time.Minute - revalidateInterval = 10 * time.Second - copyNodesInterval = 30 * time.Second - seedMinTableTime = 5 * time.Minute - seedCount = 30 - seedMaxAge = 5 * 24 * time.Hour + refreshInterval = 30 * time.Minute + revalidateInterval = 10 * time.Second + copyNodesInterval = 30 * time.Second + seedMinTableTime = 5 * time.Minute + seedCount = 30 + seedMaxAge = 5 * 24 * time.Hour ) +// Table is the 'node table', a Kademlia-like index of neighbor nodes. The table keeps +// itself up-to-date by verifying the liveness of neighbors and requesting their node +// records when announcements of a new record version are received. type Table struct { mutex sync.Mutex // protects buckets, bucket content, nursery, rand buckets [nBuckets]*bucket // index of known nodes by distance @@ -71,26 +71,24 @@ type Table struct { rand *mrand.Rand // source of randomness, periodically reseeded ips netutil.DistinctNetSet + log log.Logger db *enode.DB // database of known nodes net transport refreshReq chan chan struct{} initDone chan struct{} - - closeOnce sync.Once - closeReq chan struct{} - closed chan struct{} + closeReq chan struct{} + closed chan struct{} nodeAddedHook func(*node) // for testing } -// transport is implemented by the UDP transport. -// it is an interface so we can test without opening lots of UDP -// sockets and without generating a private key. +// transport is implemented by the UDP transports. type transport interface { - self() *enode.Node - ping(enode.ID, *net.UDPAddr) error - findnode(toid enode.ID, addr *net.UDPAddr, target encPubkey) ([]*node, error) - close() + Self() *enode.Node + RequestENR(*enode.Node) (*enode.Node, error) + lookupRandom() []*enode.Node + lookupSelf() []*enode.Node + ping(*enode.Node) (seq uint64, err error) } // bucket contains nodes, ordered by their last activity. the entry @@ -101,7 +99,7 @@ type bucket struct { ips netutil.DistinctNetSet } -func newTable(t transport, db *enode.DB, bootnodes []*enode.Node) (*Table, error) { +func newTable(t transport, db *enode.DB, bootnodes []*enode.Node, log log.Logger) (*Table, error) { tab := &Table{ net: t, db: db, @@ -111,6 +109,7 @@ func newTable(t transport, db *enode.DB, bootnodes []*enode.Node) (*Table, error closed: make(chan struct{}), rand: mrand.New(mrand.NewSource(0)), ips: netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit}, + log: log, } if err := tab.setFallbackNodes(bootnodes); err != nil { return nil, err @@ -123,12 +122,11 @@ func newTable(t transport, db *enode.DB, bootnodes []*enode.Node) (*Table, error tab.seedRand() tab.loadSeedNodes() - go tab.loop() return tab, nil } func (tab *Table) self() *enode.Node { - return tab.net.self() + return tab.net.Self() } func (tab *Table) seedRand() { @@ -149,47 +147,38 @@ func (tab *Table) ReadRandomNodes(buf []*enode.Node) (n int) { tab.mutex.Lock() defer tab.mutex.Unlock() - // Find all non-empty buckets and get a fresh slice of their entries. - var buckets [][]*node + var nodes []*enode.Node for _, b := range &tab.buckets { - if len(b.entries) > 0 { - buckets = append(buckets, b.entries) + for _, n := range b.entries { + nodes = append(nodes, unwrapNode(n)) } } - if len(buckets) == 0 { - return 0 + // Shuffle. + for i := 0; i < len(nodes); i++ { + j := tab.rand.Intn(len(nodes)) + nodes[i], nodes[j] = nodes[j], nodes[i] } - // Shuffle the buckets. - for i := len(buckets) - 1; i > 0; i-- { - j := tab.rand.Intn(len(buckets)) - buckets[i], buckets[j] = buckets[j], buckets[i] - } - // Move head of each bucket into buf, removing buckets that become empty. - var i, j int - for ; i < len(buf); i, j = i+1, (j+1)%len(buckets) { - b := buckets[j] - buf[i] = unwrapNode(b[0]) - buckets[j] = b[1:] - if len(b) == 1 { - buckets = append(buckets[:j], buckets[j+1:]...) - } - if len(buckets) == 0 { - break - } - } - return i + 1 + return copy(buf, nodes) } -// Close terminates the network listener and flushes the node database. -func (tab *Table) Close() { - tab.closeOnce.Do(func() { - if tab.net != nil { - tab.net.close() +// getNode returns the node with the given ID or nil if it isn't in the table. +func (tab *Table) getNode(id enode.ID) *enode.Node { + tab.mutex.Lock() + defer tab.mutex.Unlock() + + b := tab.bucket(id) + for _, e := range b.entries { + if e.ID() == id { + return unwrapNode(e) } - // Wait for loop to end. - close(tab.closeReq) - <-tab.closed - }) + } + return nil +} + +// close terminates the network listener and flushes the node database. +func (tab *Table) close() { + close(tab.closeReq) + <-tab.closed } // setFallbackNodes sets the initial points of contact. These nodes @@ -215,124 +204,6 @@ func (tab *Table) isInitDone() bool { } } -// Resolve searches for a specific node with the given ID. -// It returns nil if the node could not be found. -func (tab *Table) Resolve(n *enode.Node) *enode.Node { - // If the node is present in the local table, no - // network interaction is required. - hash := n.ID() - tab.mutex.Lock() - cl := tab.closest(hash, 1) - tab.mutex.Unlock() - if len(cl.entries) > 0 && cl.entries[0].ID() == hash { - return unwrapNode(cl.entries[0]) - } - // Otherwise, do a network lookup. - result := tab.lookup(encodePubkey(n.Pubkey()), true) - for _, n := range result { - if n.ID() == hash { - return unwrapNode(n) - } - } - return nil -} - -// LookupRandom finds random nodes in the network. -func (tab *Table) LookupRandom() []*enode.Node { - var target encPubkey - crand.Read(target[:]) - return unwrapNodes(tab.lookup(target, true)) -} - -// lookup performs a network search for nodes close to the given target. It approaches the -// target by querying nodes that are closer to it on each iteration. The given target does -// not need to be an actual node identifier. -func (tab *Table) lookup(targetKey encPubkey, refreshIfEmpty bool) []*node { - var ( - target = enode.ID(crypto.Keccak256Hash(targetKey[:])) - asked = make(map[enode.ID]bool) - seen = make(map[enode.ID]bool) - reply = make(chan []*node, alpha) - pendingQueries = 0 - result *nodesByDistance - ) - // don't query further if we hit ourself. - // unlikely to happen often in practice. - asked[tab.self().ID()] = true - - for { - tab.mutex.Lock() - // generate initial result set - result = tab.closest(target, bucketSize) - tab.mutex.Unlock() - if len(result.entries) > 0 || !refreshIfEmpty { - break - } - // The result set is empty, all nodes were dropped, refresh. - // We actually wait for the refresh to complete here. The very - // first query will hit this case and run the bootstrapping - // logic. - <-tab.refresh() - refreshIfEmpty = false - } - - for { - // ask the alpha closest nodes that we haven't asked yet - for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ { - n := result.entries[i] - if !asked[n.ID()] { - asked[n.ID()] = true - pendingQueries++ - go tab.findnode(n, targetKey, reply) - } - } - if pendingQueries == 0 { - // we have asked all closest nodes, stop the search - break - } - select { - case nodes := <-reply: - for _, n := range nodes { - if n != nil && !seen[n.ID()] { - seen[n.ID()] = true - result.push(n, bucketSize) - } - } - case <-tab.closeReq: - return nil // shutdown, no need to continue. - } - pendingQueries-- - } - return result.entries -} - -func (tab *Table) findnode(n *node, targetKey encPubkey, reply chan<- []*node) { - fails := tab.db.FindFails(n.ID(), n.IP()) - r, err := tab.net.findnode(n.ID(), n.addr(), targetKey) - if err == errClosed { - // Avoid recording failures on shutdown. - reply <- nil - return - } else if len(r) == 0 { - fails++ - tab.db.UpdateFindFails(n.ID(), n.IP(), fails) - log.Trace("Findnode failed", "id", n.ID(), "failcount", fails, "err", err) - if fails >= maxFindnodeFailures { - log.Trace("Too many findnode failures, dropping", "id", n.ID(), "failcount", fails) - tab.delete(n) - } - } else if fails > 0 { - tab.db.UpdateFindFails(n.ID(), n.IP(), fails-1) - } - - // Grab as many nodes as possible. Some of them might not be alive anymore, but we'll - // just remove those again during revalidation. - for _, n := range r { - tab.addSeenNode(n) - } - reply <- r -} - func (tab *Table) refresh() <-chan struct{} { done := make(chan struct{}) select { @@ -343,7 +214,7 @@ func (tab *Table) refresh() <-chan struct{} { return done } -// loop schedules refresh, revalidate runs and coordinates shutdown. +// loop schedules runs of doRefresh, doRevalidate and copyLiveNodes. func (tab *Table) loop() { var ( revalidate = time.NewTimer(tab.nextRevalidateTime()) @@ -405,9 +276,8 @@ loop: close(tab.closed) } -// doRefresh performs a lookup for a random target to keep buckets -// full. seed nodes are inserted if the table is empty (initial -// bootstrap or discarded faulty peers). +// doRefresh performs a lookup for a random target to keep buckets full. seed nodes are +// inserted if the table is empty (initial bootstrap or discarded faulty peers). func (tab *Table) doRefresh(done chan struct{}) { defer close(done) @@ -417,11 +287,7 @@ func (tab *Table) doRefresh(done chan struct{}) { tab.loadSeedNodes() // Run self lookup to discover new neighbor nodes. - // We can only do this if we have a secp256k1 identity. - var key ecdsa.PublicKey - if err := tab.self().Load((*enode.Secp256k1)(&key)); err == nil { - tab.lookup(encodePubkey(&key), false) - } + tab.net.lookupSelf() // The Kademlia paper specifies that the bucket refresh should // perform a lookup in the least recently used bucket. We cannot @@ -430,9 +296,7 @@ func (tab *Table) doRefresh(done chan struct{}) { // sha3 preimage that falls into a chosen bucket. // We perform a few lookups with a random target instead. for i := 0; i < 3; i++ { - var target encPubkey - crand.Read(target[:]) - tab.lookup(target, false) + tab.net.lookupRandom() } } @@ -442,13 +306,13 @@ func (tab *Table) loadSeedNodes() { for i := range seeds { seed := seeds[i] age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP())) }} - log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age) + tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age) tab.addSeenNode(seed) } } -// doRevalidate checks that the last node in a random bucket is still live -// and replaces or deletes the node if it isn't. +// doRevalidate checks that the last node in a random bucket is still live and replaces or +// deletes the node if it isn't. func (tab *Table) doRevalidate(done chan<- struct{}) { defer func() { done <- struct{}{} }() @@ -459,7 +323,17 @@ func (tab *Table) doRevalidate(done chan<- struct{}) { } // Ping the selected node and wait for a pong. - err := tab.net.ping(last.ID(), last.addr()) + remoteSeq, err := tab.net.ping(unwrapNode(last)) + + // Also fetch record if the node replied and returned a higher sequence number. + if last.Seq() < remoteSeq { + n, err := tab.net.RequestENR(unwrapNode(last)) + if err != nil { + tab.log.Debug("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err) + } else { + last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks} + } + } tab.mutex.Lock() defer tab.mutex.Unlock() @@ -467,16 +341,16 @@ func (tab *Table) doRevalidate(done chan<- struct{}) { if err == nil { // The node responded, move it to the front. last.livenessChecks++ - log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks) + tab.log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks) tab.bumpInBucket(b, last) return } // No reply received, pick a replacement or delete the node if there aren't // any replacements. if r := tab.replace(b, last); r != nil { - log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP()) + tab.log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP()) } else { - log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks) + tab.log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks) } } @@ -520,22 +394,27 @@ func (tab *Table) copyLiveNodes() { // closest returns the n nodes in the table that are closest to the // given id. The caller must hold tab.mutex. -func (tab *Table) closest(target enode.ID, nresults int) *nodesByDistance { +func (tab *Table) closest(target enode.ID, nresults int, checklive bool) *nodesByDistance { // This is a very wasteful way to find the closest nodes but // obviously correct. I believe that tree-based buckets would make // this easier to implement efficiently. close := &nodesByDistance{target: target} for _, b := range &tab.buckets { for _, n := range b.entries { - if n.livenessChecks > 0 { - close.push(n, nresults) + if checklive && n.livenessChecks == 0 { + continue } + close.push(n, nresults) } } return close } +// len returns the number of nodes in the table. func (tab *Table) len() (n int) { + tab.mutex.Lock() + defer tab.mutex.Unlock() + for _, b := range &tab.buckets { n += len(b.entries) } @@ -641,11 +520,11 @@ func (tab *Table) addIP(b *bucket, ip net.IP) bool { return true } if !tab.ips.Add(ip) { - log.Debug("IP exceeds table limit", "ip", ip) + tab.log.Debug("IP exceeds table limit", "ip", ip) return false } if !b.ips.Add(ip) { - log.Debug("IP exceeds bucket limit", "ip", ip) + tab.log.Debug("IP exceeds bucket limit", "ip", ip) tab.ips.Remove(ip) return false } @@ -754,8 +633,7 @@ func deleteNode(list []*node, n *node) []*node { return list } -// nodesByDistance is a list of nodes, ordered by -// distance to target. +// nodesByDistance is a list of nodes, ordered by distance to target. type nodesByDistance struct { entries []*node target enode.ID diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discover/udp.go b/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go similarity index 52% rename from vendor/github.com/ethereum/go-ethereum/p2p/discover/udp.go rename to vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go index df9a3065f..a8f7101b0 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discover/udp.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discover/v4_udp.go @@ -1,4 +1,4 @@ -// Copyright 2015 The go-ethereum Authors +// Copyright 2019 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 @@ -20,8 +20,10 @@ import ( "bytes" "container/list" "crypto/ecdsa" + crand "crypto/rand" "errors" "fmt" + "io" "net" "sync" "time" @@ -29,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/rlp" ) @@ -45,28 +48,35 @@ var ( errClosed = errors.New("socket closed") ) -// Timeouts const ( respTimeout = 500 * time.Millisecond expiration = 20 * time.Second bondExpiration = 24 * time.Hour + maxFindnodeFailures = 5 // nodes exceeding this limit are dropped ntpFailureThreshold = 32 // Continuous timeouts after which to check NTP ntpWarningCooldown = 10 * time.Minute // Minimum amount of time to pass before repeating NTP warning driftThreshold = 10 * time.Second // Allowed clock drift before warning user + + // Discovery packets are defined to be no larger than 1280 bytes. + // Packets larger than this size will be cut at the end and treated + // as invalid because their hash won't match. + maxPacketSize = 1280 ) // RPC packet types const ( - pingPacket = iota + 1 // zero is 'reserved' - pongPacket - findnodePacket - neighborsPacket + p_pingV4 = iota + 1 // zero is 'reserved' + p_pongV4 + p_findnodeV4 + p_neighborsV4 + p_enrRequestV4 + p_enrResponseV4 ) // RPC request structures type ( - ping struct { + pingV4 struct { senderKey *ecdsa.PublicKey // filled in by preverify Version uint @@ -76,8 +86,8 @@ type ( Rest []rlp.RawValue `rlp:"tail"` } - // pong is the reply to ping. - pong struct { + // pongV4 is the reply to pingV4. + pongV4 struct { // This field should mirror the UDP envelope address // of the ping packet, which provides a way to discover the // the external address (after NAT). @@ -89,22 +99,37 @@ type ( Rest []rlp.RawValue `rlp:"tail"` } - // findnode is a query for nodes close to the given target. - findnode struct { + // findnodeV4 is a query for nodes close to the given target. + findnodeV4 struct { Target encPubkey Expiration uint64 // Ignore additional fields (for forward compatibility). Rest []rlp.RawValue `rlp:"tail"` } - // reply to findnode - neighbors struct { + // neighborsV4 is the reply to findnodeV4. + neighborsV4 struct { Nodes []rpcNode Expiration uint64 // Ignore additional fields (for forward compatibility). Rest []rlp.RawValue `rlp:"tail"` } + // enrRequestV4 queries for the remote node's record. + enrRequestV4 struct { + Expiration uint64 + // Ignore additional fields (for forward compatibility). + Rest []rlp.RawValue `rlp:"tail"` + } + + // enrResponseV4 is the reply to enrRequestV4. + enrResponseV4 struct { + ReplyTok []byte // Hash of the enrRequest packet. + Record enr.Record + // Ignore additional fields (for forward compatibility). + Rest []rlp.RawValue `rlp:"tail"` + } + rpcNode struct { IP net.IP // len 4 for IPv4 or 16 for IPv6 UDP uint16 // for discovery protocol @@ -119,6 +144,17 @@ type ( } ) +// packetV4 is implemented by all v4 protocol messages. +type packetV4 interface { + // preverify checks whether the packet is valid and should be handled at all. + preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error + // handle handles the packet. + handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) + // packet name and type for logging purposes. + name() string + kind() byte +} + func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { ip := net.IP{} if ip4 := addr.IP.To4(); ip4 != nil { @@ -129,7 +165,7 @@ func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} } -func (t *udp) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) { +func (t *UDPv4) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) { if rn.UDP <= 1024 { return nil, errors.New("low port") } @@ -157,31 +193,16 @@ func nodeToRPC(n *node) rpcNode { return rpcNode{ID: ekey, IP: n.IP(), UDP: uint16(n.UDP()), TCP: uint16(n.TCP())} } -// packet is implemented by all protocol messages. -type packet interface { - // preverify checks whether the packet is valid and should be handled at all. - preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error - // handle handles the packet. - handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) - // name returns the name of the packet for logging purposes. - name() string -} - -type conn interface { - ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) - WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) - Close() error - LocalAddr() net.Addr -} - -// udp implements the discovery v4 UDP wire protocol. -type udp struct { - conn conn +// UDPv4 implements the v4 wire protocol. +type UDPv4 struct { + conn UDPConn + log log.Logger netrestrict *netutil.Netlist priv *ecdsa.PrivateKey localNode *enode.LocalNode db *enode.DB tab *Table + closeOnce sync.Once wg sync.WaitGroup addReplyMatcher chan *replyMatcher @@ -189,7 +210,7 @@ type udp struct { closing chan struct{} } -// pending represents a pending reply. +// replyMatcher represents a pending reply. // // Some implementations of the protocol wish to send more than one // reply packet to findnode. In general, any neighbors packet cannot @@ -215,50 +236,27 @@ type replyMatcher struct { // errc receives nil when the callback indicates completion or an // error if no further reply is received within the timeout. - errc chan<- error + errc chan error + + // reply contains the most recent reply. This field is safe for reading after errc has + // received a value. + reply packetV4 } type replyMatchFunc func(interface{}) (matched bool, requestDone bool) +// reply is a reply packet from a certain node. type reply struct { - from enode.ID - ip net.IP - ptype byte - data packet - + from enode.ID + ip net.IP + data packetV4 // loop indicates whether there was // a matching request by sending on this channel. matched chan<- bool } -// ReadPacket is sent to the unhandled channel when it could not be processed -type ReadPacket struct { - Data []byte - Addr *net.UDPAddr -} - -// Config holds Table-related settings. -type Config struct { - // These settings are required and configure the UDP listener: - PrivateKey *ecdsa.PrivateKey - - // These settings are optional: - NetRestrict *netutil.Netlist // network whitelist - Bootnodes []*enode.Node // list of bootstrap nodes - Unhandled chan<- ReadPacket // unhandled packets are sent on this channel -} - -// ListenUDP returns a new table that listens for UDP packets on laddr. -func ListenUDP(c conn, ln *enode.LocalNode, cfg Config) (*Table, error) { - tab, _, err := newUDP(c, ln, cfg) - if err != nil { - return nil, err - } - return tab, nil -} - -func newUDP(c conn, ln *enode.LocalNode, cfg Config) (*Table, *udp, error) { - udp := &udp{ +func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { + t := &UDPv4{ conn: c, priv: cfg.PrivateKey, netrestrict: cfg.NetRestrict, @@ -267,59 +265,217 @@ func newUDP(c conn, ln *enode.LocalNode, cfg Config) (*Table, *udp, error) { closing: make(chan struct{}), gotreply: make(chan reply), addReplyMatcher: make(chan *replyMatcher), + log: cfg.Log, } - tab, err := newTable(udp, ln.Database(), cfg.Bootnodes) + if t.log == nil { + t.log = log.Root() + } + tab, err := newTable(t, ln.Database(), cfg.Bootnodes, t.log) if err != nil { - return nil, nil, err + return nil, err } - udp.tab = tab + t.tab = tab + go tab.loop() - udp.wg.Add(2) - go udp.loop() - go udp.readLoop(cfg.Unhandled) - return udp.tab, udp, nil + t.wg.Add(2) + go t.loop() + go t.readLoop(cfg.Unhandled) + return t, nil } -func (t *udp) self() *enode.Node { +// Self returns the local node. +func (t *UDPv4) Self() *enode.Node { return t.localNode.Node() } -func (t *udp) close() { - close(t.closing) - t.conn.Close() - t.wg.Wait() +// Close shuts down the socket and aborts any running queries. +func (t *UDPv4) Close() { + t.closeOnce.Do(func() { + close(t.closing) + t.conn.Close() + t.wg.Wait() + t.tab.close() + }) } -func (t *udp) ourEndpoint() rpcEndpoint { - n := t.self() +// ReadRandomNodes reads random nodes from the local table. +func (t *UDPv4) ReadRandomNodes(buf []*enode.Node) int { + return t.tab.ReadRandomNodes(buf) +} + +// LookupRandom finds random nodes in the network. +func (t *UDPv4) LookupRandom() []*enode.Node { + if t.tab.len() == 0 { + // All nodes were dropped, refresh. The very first query will hit this + // case and run the bootstrapping logic. + <-t.tab.refresh() + } + return t.lookupRandom() +} + +func (t *UDPv4) LookupPubkey(key *ecdsa.PublicKey) []*enode.Node { + if t.tab.len() == 0 { + // All nodes were dropped, refresh. The very first query will hit this + // case and run the bootstrapping logic. + <-t.tab.refresh() + } + return unwrapNodes(t.lookup(encodePubkey(key))) +} + +func (t *UDPv4) lookupRandom() []*enode.Node { + var target encPubkey + crand.Read(target[:]) + return unwrapNodes(t.lookup(target)) +} + +func (t *UDPv4) lookupSelf() []*enode.Node { + return unwrapNodes(t.lookup(encodePubkey(&t.priv.PublicKey))) +} + +// lookup performs a network search for nodes close to the given target. It approaches the +// target by querying nodes that are closer to it on each iteration. The given target does +// not need to be an actual node identifier. +func (t *UDPv4) lookup(targetKey encPubkey) []*node { + var ( + target = enode.ID(crypto.Keccak256Hash(targetKey[:])) + asked = make(map[enode.ID]bool) + seen = make(map[enode.ID]bool) + reply = make(chan []*node, alpha) + pendingQueries = 0 + result *nodesByDistance + ) + // Don't query further if we hit ourself. + // Unlikely to happen often in practice. + asked[t.Self().ID()] = true + + // Generate the initial result set. + t.tab.mutex.Lock() + result = t.tab.closest(target, bucketSize, false) + t.tab.mutex.Unlock() + + for { + // ask the alpha closest nodes that we haven't asked yet + for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ { + n := result.entries[i] + if !asked[n.ID()] { + asked[n.ID()] = true + pendingQueries++ + go t.lookupWorker(n, targetKey, reply) + } + } + if pendingQueries == 0 { + // we have asked all closest nodes, stop the search + break + } + select { + case nodes := <-reply: + for _, n := range nodes { + if n != nil && !seen[n.ID()] { + seen[n.ID()] = true + result.push(n, bucketSize) + } + } + case <-t.tab.closeReq: + return nil // shutdown, no need to continue. + } + pendingQueries-- + } + return result.entries +} + +func (t *UDPv4) lookupWorker(n *node, targetKey encPubkey, reply chan<- []*node) { + fails := t.db.FindFails(n.ID(), n.IP()) + r, err := t.findnode(n.ID(), n.addr(), targetKey) + if err == errClosed { + // Avoid recording failures on shutdown. + reply <- nil + return + } else if len(r) == 0 { + fails++ + t.db.UpdateFindFails(n.ID(), n.IP(), fails) + t.log.Trace("Findnode failed", "id", n.ID(), "failcount", fails, "err", err) + if fails >= maxFindnodeFailures { + t.log.Trace("Too many findnode failures, dropping", "id", n.ID(), "failcount", fails) + t.tab.delete(n) + } + } else if fails > 0 { + // Reset failure counter because it counts _consecutive_ failures. + t.db.UpdateFindFails(n.ID(), n.IP(), 0) + } + + // Grab as many nodes as possible. Some of them might not be alive anymore, but we'll + // just remove those again during revalidation. + for _, n := range r { + t.tab.addSeenNode(n) + } + reply <- r +} + +// Resolve searches for a specific node with the given ID and tries to get the most recent +// version of the node record for it. It returns n if the node could not be resolved. +func (t *UDPv4) Resolve(n *enode.Node) *enode.Node { + // Try asking directly. This works if the node is still responding on the endpoint we have. + if rn, err := t.RequestENR(n); err == nil { + return rn + } + // Check table for the ID, we might have a newer version there. + if intable := t.tab.getNode(n.ID()); intable != nil && intable.Seq() > n.Seq() { + n = intable + if rn, err := t.RequestENR(n); err == nil { + return rn + } + } + // Otherwise perform a network lookup. + var key enode.Secp256k1 + if n.Load(&key) != nil { + return n // no secp256k1 key + } + result := t.LookupPubkey((*ecdsa.PublicKey)(&key)) + for _, rn := range result { + if rn.ID() == n.ID() { + if rn, err := t.RequestENR(rn); err == nil { + return rn + } + } + } + return n +} + +func (t *UDPv4) ourEndpoint() rpcEndpoint { + n := t.Self() a := &net.UDPAddr{IP: n.IP(), Port: n.UDP()} return makeEndpoint(a, uint16(n.TCP())) } +// Ping sends a ping message to the given node. +func (t *UDPv4) Ping(n *enode.Node) error { + _, err := t.ping(n) + return err +} + // ping sends a ping message to the given node and waits for a reply. -func (t *udp) ping(toid enode.ID, toaddr *net.UDPAddr) error { - return <-t.sendPing(toid, toaddr, nil) +func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) { + rm := t.sendPing(n.ID(), &net.UDPAddr{IP: n.IP(), Port: n.UDP()}, nil) + if err = <-rm.errc; err == nil { + seq = seqFromTail(rm.reply.(*pongV4).Rest) + } + return seq, err } // sendPing sends a ping message to the given node and invokes the callback // when the reply arrives. -func (t *udp) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) <-chan error { - req := &ping{ - Version: 4, - From: t.ourEndpoint(), - To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB - Expiration: uint64(time.Now().Add(expiration).Unix()), - } - packet, hash, err := encodePacket(t.priv, pingPacket, req) +func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *replyMatcher { + req := t.makePing(toaddr) + packet, hash, err := t.encode(t.priv, req) if err != nil { errc := make(chan error, 1) errc <- err - return errc + return &replyMatcher{errc: errc} } // Add a matcher for the reply to the pending reply queue. Pongs are matched if they // reference the ping we're about to send. - errc := t.pending(toid, toaddr.IP, pongPacket, func(p interface{}) (matched bool, requestDone bool) { - matched = bytes.Equal(p.(*pong).ReplyTok, hash) + rm := t.pending(toid, toaddr.IP, p_pongV4, func(p interface{}) (matched bool, requestDone bool) { + matched = bytes.Equal(p.(*pongV4).ReplyTok, hash) if matched && callback != nil { callback() } @@ -328,47 +484,92 @@ func (t *udp) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) <-ch // Send the packet. t.localNode.UDPContact(toaddr) t.write(toaddr, toid, req.name(), packet) - return errc + return rm +} + +func (t *UDPv4) makePing(toaddr *net.UDPAddr) *pingV4 { + seq, _ := rlp.EncodeToBytes(t.localNode.Node().Seq()) + return &pingV4{ + Version: 4, + From: t.ourEndpoint(), + To: makeEndpoint(toaddr, 0), + Expiration: uint64(time.Now().Add(expiration).Unix()), + Rest: []rlp.RawValue{seq}, + } } // findnode sends a findnode request to the given node and waits until // the node has sent up to k neighbors. -func (t *udp) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { - // If we haven't seen a ping from the destination node for a while, it won't remember - // our endpoint proof and reject findnode. Solicit a ping first. - if time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration { - t.ping(toid, toaddr) - // Wait for them to ping back and process our pong. - time.Sleep(respTimeout) - } +func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) { + t.ensureBond(toid, toaddr) // Add a matcher for 'neighbours' replies to the pending reply queue. The matcher is // active until enough nodes have been received. nodes := make([]*node, 0, bucketSize) nreceived := 0 - errc := t.pending(toid, toaddr.IP, neighborsPacket, func(r interface{}) (matched bool, requestDone bool) { - reply := r.(*neighbors) + rm := t.pending(toid, toaddr.IP, p_neighborsV4, func(r interface{}) (matched bool, requestDone bool) { + reply := r.(*neighborsV4) for _, rn := range reply.Nodes { nreceived++ n, err := t.nodeFromRPC(toaddr, rn) if err != nil { - log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err) + t.log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err) continue } nodes = append(nodes, n) } return true, nreceived >= bucketSize }) - t.send(toaddr, toid, findnodePacket, &findnode{ + t.send(toaddr, toid, &findnodeV4{ Target: target, Expiration: uint64(time.Now().Add(expiration).Unix()), }) - return nodes, <-errc + return nodes, <-rm.errc +} + +// RequestENR sends enrRequest to the given node and waits for a response. +func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) { + addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()} + t.ensureBond(n.ID(), addr) + + req := &enrRequestV4{ + Expiration: uint64(time.Now().Add(expiration).Unix()), + } + packet, hash, err := t.encode(t.priv, req) + if err != nil { + return nil, err + } + // Add a matcher for the reply to the pending reply queue. Responses are matched if + // they reference the request we're about to send. + rm := t.pending(n.ID(), addr.IP, p_enrResponseV4, func(r interface{}) (matched bool, requestDone bool) { + matched = bytes.Equal(r.(*enrResponseV4).ReplyTok, hash) + return matched, matched + }) + // Send the packet and wait for the reply. + t.write(addr, n.ID(), req.name(), packet) + if err := <-rm.errc; err != nil { + return nil, err + } + // Verify the response record. + respN, err := enode.New(enode.ValidSchemes, &rm.reply.(*enrResponseV4).Record) + if err != nil { + return nil, err + } + if respN.ID() != n.ID() { + return nil, fmt.Errorf("invalid ID in response record") + } + if respN.Seq() < n.Seq() { + return n, nil // response record is older + } + if err := netutil.CheckRelayIP(addr.IP, respN.IP()); err != nil { + return nil, fmt.Errorf("invalid IP in response record: %v", err) + } + return respN, nil } // pending adds a reply matcher to the pending reply queue. // see the documentation of type replyMatcher for a detailed explanation. -func (t *udp) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchFunc) <-chan error { +func (t *UDPv4) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchFunc) *replyMatcher { ch := make(chan error, 1) p := &replyMatcher{from: id, ip: ip, ptype: ptype, callback: callback, errc: ch} select { @@ -377,15 +578,15 @@ func (t *udp) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchFun case <-t.closing: ch <- errClosed } - return ch + return p } // handleReply dispatches a reply packet, invoking reply matchers. It returns // whether any matcher considered the packet acceptable. -func (t *udp) handleReply(from enode.ID, fromIP net.IP, ptype byte, req packet) bool { +func (t *UDPv4) handleReply(from enode.ID, fromIP net.IP, req packetV4) bool { matched := make(chan bool, 1) select { - case t.gotreply <- reply{from, fromIP, ptype, req, matched}: + case t.gotreply <- reply{from, fromIP, req, matched}: // loop will handle it return <-matched case <-t.closing: @@ -395,7 +596,7 @@ func (t *udp) handleReply(from enode.ID, fromIP net.IP, ptype byte, req packet) // loop runs in its own goroutine. it keeps track of // the refresh timer and the pending reply queue. -func (t *udp) loop() { +func (t *UDPv4) loop() { defer t.wg.Done() var ( @@ -448,11 +649,12 @@ func (t *udp) loop() { var matched bool // whether any replyMatcher considered the reply acceptable. for el := plist.Front(); el != nil; el = el.Next() { p := el.Value.(*replyMatcher) - if p.from == r.from && p.ptype == r.ptype && p.ip.Equal(r.ip) { + if p.from == r.from && p.ptype == r.data.kind() && p.ip.Equal(r.ip) { ok, requestDone := p.callback(r.data) matched = matched || ok // Remove the matcher if callback indicates that all replies have been received. if requestDone { + p.reply = r.data p.errc <- nil plist.Remove(el) } @@ -496,13 +698,13 @@ var ( headSpace = make([]byte, headSize) // Neighbors replies are sent across multiple packets to - // stay below the 1280 byte limit. We compute the maximum number + // stay below the packet size limit. We compute the maximum number // of entries by stuffing a packet until it grows too large. maxNeighbors int ) func init() { - p := neighbors{Expiration: ^uint64(0)} + p := neighborsV4{Expiration: ^uint64(0)} maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} for n := 0; ; n++ { p.Nodes = append(p.Nodes, maxSizeNode) @@ -511,39 +713,40 @@ func init() { // If this ever happens, it will be caught by the unit tests. panic("cannot encode: " + err.Error()) } - if headSize+size+1 >= 1280 { + if headSize+size+1 >= maxPacketSize { maxNeighbors = n break } } } -func (t *udp) send(toaddr *net.UDPAddr, toid enode.ID, ptype byte, req packet) ([]byte, error) { - packet, hash, err := encodePacket(t.priv, ptype, req) +func (t *UDPv4) send(toaddr *net.UDPAddr, toid enode.ID, req packetV4) ([]byte, error) { + packet, hash, err := t.encode(t.priv, req) if err != nil { return hash, err } return hash, t.write(toaddr, toid, req.name(), packet) } -func (t *udp) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error { +func (t *UDPv4) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error { _, err := t.conn.WriteToUDP(packet, toaddr) - log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err) + t.log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err) return err } -func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (packet, hash []byte, err error) { +func (t *UDPv4) encode(priv *ecdsa.PrivateKey, req packetV4) (packet, hash []byte, err error) { + name := req.name() b := new(bytes.Buffer) b.Write(headSpace) - b.WriteByte(ptype) + b.WriteByte(req.kind()) if err := rlp.Encode(b, req); err != nil { - log.Error("Can't encode discv4 packet", "err", err) + t.log.Error(fmt.Sprintf("Can't encode %s packet", name), "err", err) return nil, nil, err } packet = b.Bytes() sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv) if err != nil { - log.Error("Can't sign discv4 packet", "err", err) + t.log.Error(fmt.Sprintf("Can't sign %s packet", name), "err", err) return nil, nil, err } copy(packet[macSize:], sig) @@ -556,25 +759,24 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (packet, } // readLoop runs in its own goroutine. it handles incoming UDP packets. -func (t *udp) readLoop(unhandled chan<- ReadPacket) { +func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) { defer t.wg.Done() if unhandled != nil { defer close(unhandled) } - // Discovery packets are defined to be no larger than 1280 bytes. - // Packets larger than this size will be cut at the end and treated - // as invalid because their hash won't match. - buf := make([]byte, 1280) + buf := make([]byte, maxPacketSize) for { nbytes, from, err := t.conn.ReadFromUDP(buf) if netutil.IsTemporaryError(err) { // Ignore temporary read errors. - log.Debug("Temporary UDP read error", "err", err) + t.log.Debug("Temporary UDP read error", "err", err) continue } else if err != nil { // Shut down the loop for permament errors. - log.Debug("UDP read error", "err", err) + if err != io.EOF { + t.log.Debug("UDP read error", "err", err) + } return } if t.handlePacket(from, buf[:nbytes]) != nil && unhandled != nil { @@ -586,24 +788,24 @@ func (t *udp) readLoop(unhandled chan<- ReadPacket) { } } -func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { - packet, fromKey, hash, err := decodePacket(buf) +func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error { + packet, fromKey, hash, err := decodeV4(buf) if err != nil { - log.Debug("Bad discv4 packet", "addr", from, "err", err) + t.log.Debug("Bad discv4 packet", "addr", from, "err", err) return err } fromID := fromKey.id() if err == nil { err = packet.preverify(t, from, fromID, fromKey) } - log.Trace("<< "+packet.name(), "id", fromID, "addr", from, "err", err) + t.log.Trace("<< "+packet.name(), "id", fromID, "addr", from, "err", err) if err == nil { packet.handle(t, from, fromID, hash) } return err } -func decodePacket(buf []byte) (packet, encPubkey, []byte, error) { +func decodeV4(buf []byte) (packetV4, encPubkey, []byte, error) { if len(buf) < headSize+1 { return nil, encPubkey{}, nil, errPacketTooSmall } @@ -617,16 +819,20 @@ func decodePacket(buf []byte) (packet, encPubkey, []byte, error) { return nil, fromKey, hash, err } - var req packet + var req packetV4 switch ptype := sigdata[0]; ptype { - case pingPacket: - req = new(ping) - case pongPacket: - req = new(pong) - case findnodePacket: - req = new(findnode) - case neighborsPacket: - req = new(neighbors) + case p_pingV4: + req = new(pingV4) + case p_pongV4: + req = new(pongV4) + case p_findnodeV4: + req = new(findnodeV4) + case p_neighborsV4: + req = new(neighborsV4) + case p_enrRequestV4: + req = new(enrRequestV4) + case p_enrResponseV4: + req = new(enrResponseV4) default: return nil, fromKey, hash, fmt.Errorf("unknown type: %d", ptype) } @@ -635,9 +841,43 @@ func decodePacket(buf []byte) (packet, encPubkey, []byte, error) { return req, fromKey, hash, err } -// Packet Handlers +// checkBond checks if the given node has a recent enough endpoint proof. +func (t *UDPv4) checkBond(id enode.ID, ip net.IP) bool { + return time.Since(t.db.LastPongReceived(id, ip)) < bondExpiration +} -func (req *ping) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { +// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while. +// This ensures there is a valid endpoint proof on the remote end. +func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) { + tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration + if tooOld || t.db.FindFails(toid, toaddr.IP) > maxFindnodeFailures { + rm := t.sendPing(toid, toaddr, nil) + <-rm.errc + // Wait for them to ping back and process our pong. + time.Sleep(respTimeout) + } +} + +// expired checks whether the given UNIX time stamp is in the past. +func expired(ts uint64) bool { + return time.Unix(int64(ts), 0).Before(time.Now()) +} + +func seqFromTail(tail []rlp.RawValue) uint64 { + if len(tail) == 0 { + return 0 + } + var seq uint64 + rlp.DecodeBytes(tail[0], &seq) + return seq +} + +// PING/v4 + +func (req *pingV4) name() string { return "PING/v4" } +func (req *pingV4) kind() byte { return p_pingV4 } + +func (req *pingV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { if expired(req.Expiration) { return errExpired } @@ -649,12 +889,14 @@ func (req *ping) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey e return nil } -func (req *ping) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { +func (req *pingV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { // Reply. - t.send(from, fromID, pongPacket, &pong{ + seq, _ := rlp.EncodeToBytes(t.localNode.Node().Seq()) + t.send(from, fromID, &pongV4{ To: makeEndpoint(from, req.From.TCP), ReplyTok: mac, Expiration: uint64(time.Now().Add(expiration).Unix()), + Rest: []rlp.RawValue{seq}, }) // Ping back if our last pong on file is too far in the past. @@ -672,30 +914,36 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) } -func (req *ping) name() string { return "PING/v4" } +// PONG/v4 -func (req *pong) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { +func (req *pongV4) name() string { return "PONG/v4" } +func (req *pongV4) kind() byte { return p_pongV4 } + +func (req *pongV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { if expired(req.Expiration) { return errExpired } - if !t.handleReply(fromID, from.IP, pongPacket, req) { + if !t.handleReply(fromID, from.IP, req) { return errUnsolicitedReply } return nil } -func (req *pong) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { +func (req *pongV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) t.db.UpdateLastPongReceived(fromID, from.IP, time.Now()) } -func (req *pong) name() string { return "PONG/v4" } +// FINDNODE/v4 -func (req *findnode) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { +func (req *findnodeV4) name() string { return "FINDNODE/v4" } +func (req *findnodeV4) kind() byte { return p_findnodeV4 } + +func (req *findnodeV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { if expired(req.Expiration) { return errExpired } - if time.Since(t.db.LastPongReceived(fromID, from.IP)) > bondExpiration { + if !t.checkBond(fromID, from.IP) { // No endpoint proof pong exists, we don't process the packet. This prevents an // attack vector where the discovery protocol could be used to amplify traffic in a // DDOS attack. A malicious actor would send a findnode request with the IP address @@ -707,49 +955,83 @@ func (req *findnode) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromK return nil } -func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { +func (req *findnodeV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { // Determine closest nodes. target := enode.ID(crypto.Keccak256Hash(req.Target[:])) t.tab.mutex.Lock() - closest := t.tab.closest(target, bucketSize).entries + closest := t.tab.closest(target, bucketSize, true).entries t.tab.mutex.Unlock() // Send neighbors in chunks with at most maxNeighbors per packet - // to stay below the 1280 byte limit. - p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} + // to stay below the packet size limit. + p := neighborsV4{Expiration: uint64(time.Now().Add(expiration).Unix())} var sent bool for _, n := range closest { if netutil.CheckRelayIP(from.IP, n.IP()) == nil { p.Nodes = append(p.Nodes, nodeToRPC(n)) } if len(p.Nodes) == maxNeighbors { - t.send(from, fromID, neighborsPacket, &p) + t.send(from, fromID, &p) p.Nodes = p.Nodes[:0] sent = true } } if len(p.Nodes) > 0 || !sent { - t.send(from, fromID, neighborsPacket, &p) + t.send(from, fromID, &p) } } -func (req *findnode) name() string { return "FINDNODE/v4" } +// NEIGHBORS/v4 -func (req *neighbors) preverify(t *udp, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { +func (req *neighborsV4) name() string { return "NEIGHBORS/v4" } +func (req *neighborsV4) kind() byte { return p_neighborsV4 } + +func (req *neighborsV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { if expired(req.Expiration) { return errExpired } - if !t.handleReply(fromID, from.IP, neighborsPacket, req) { + if !t.handleReply(fromID, from.IP, req) { return errUnsolicitedReply } return nil } -func (req *neighbors) handle(t *udp, from *net.UDPAddr, fromID enode.ID, mac []byte) { +func (req *neighborsV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { } -func (req *neighbors) name() string { return "NEIGHBORS/v4" } +// ENRREQUEST/v4 -func expired(ts uint64) bool { - return time.Unix(int64(ts), 0).Before(time.Now()) +func (req *enrRequestV4) name() string { return "ENRREQUEST/v4" } +func (req *enrRequestV4) kind() byte { return p_enrRequestV4 } + +func (req *enrRequestV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { + if expired(req.Expiration) { + return errExpired + } + if !t.checkBond(fromID, from.IP) { + return errUnknownNode + } + return nil +} + +func (req *enrRequestV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { + t.send(from, fromID, &enrResponseV4{ + ReplyTok: mac, + Record: *t.localNode.Node().Record(), + }) +} + +// ENRRESPONSE/v4 + +func (req *enrResponseV4) name() string { return "ENRRESPONSE/v4" } +func (req *enrResponseV4) kind() byte { return p_enrResponseV4 } + +func (req *enrResponseV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromKey encPubkey) error { + if !t.handleReply(fromID, from.IP, req) { + return errUnsolicitedReply + } + return nil +} + +func (req *enrResponseV4) handle(t *UDPv4, from *net.UDPAddr, fromID enode.ID, mac []byte) { } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/metrics.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/metrics.go index cb11d7eac..e68d53c13 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/metrics.go @@ -1,3 +1,19 @@ +// 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 discv5 import "github.com/ethereum/go-ethereum/metrics" diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/localnode.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/localnode.go index 623f8eae1..d8aa02a77 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enode/localnode.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/localnode.go @@ -48,23 +48,32 @@ type LocalNode struct { db *DB // everything below is protected by a lock - mu sync.Mutex - seq uint64 - entries map[string]enr.Entry - udpTrack *netutil.IPTracker // predicts external UDP endpoint - staticIP net.IP - fallbackIP net.IP - fallbackUDP int + mu sync.Mutex + seq uint64 + entries map[string]enr.Entry + endpoint4 lnEndpoint + endpoint6 lnEndpoint +} + +type lnEndpoint struct { + track *netutil.IPTracker + staticIP, fallbackIP net.IP + fallbackUDP int } // NewLocalNode creates a local node. func NewLocalNode(db *DB, key *ecdsa.PrivateKey) *LocalNode { ln := &LocalNode{ - id: PubkeyToIDV4(&key.PublicKey), - db: db, - key: key, - udpTrack: netutil.NewIPTracker(iptrackWindow, iptrackContactWindow, iptrackMinStatements), - entries: make(map[string]enr.Entry), + id: PubkeyToIDV4(&key.PublicKey), + db: db, + key: key, + entries: make(map[string]enr.Entry), + endpoint4: lnEndpoint{ + track: netutil.NewIPTracker(iptrackWindow, iptrackContactWindow, iptrackMinStatements), + }, + endpoint6: lnEndpoint{ + track: netutil.NewIPTracker(iptrackWindow, iptrackContactWindow, iptrackMinStatements), + }, } ln.seq = db.localSeq(ln.id) ln.invalidate() @@ -89,13 +98,22 @@ func (ln *LocalNode) Node() *Node { return ln.cur.Load().(*Node) } +// Seq returns the current sequence number of the local node record. +func (ln *LocalNode) Seq() uint64 { + ln.mu.Lock() + defer ln.mu.Unlock() + + return ln.seq +} + // ID returns the local node ID. func (ln *LocalNode) ID() ID { return ln.id } -// Set puts the given entry into the local record, overwriting -// any existing value. +// Set puts the given entry into the local record, overwriting any existing value. +// Use Set*IP and SetFallbackUDP to set IP addresses and UDP port, otherwise they'll +// be overwritten by the endpoint predictor. func (ln *LocalNode) Set(e enr.Entry) { ln.mu.Lock() defer ln.mu.Unlock() @@ -127,13 +145,20 @@ func (ln *LocalNode) delete(e enr.Entry) { } } +func (ln *LocalNode) endpointForIP(ip net.IP) *lnEndpoint { + if ip.To4() != nil { + return &ln.endpoint4 + } + return &ln.endpoint6 +} + // SetStaticIP sets the local IP to the given one unconditionally. // This disables endpoint prediction. func (ln *LocalNode) SetStaticIP(ip net.IP) { ln.mu.Lock() defer ln.mu.Unlock() - ln.staticIP = ip + ln.endpointForIP(ip).staticIP = ip ln.updateEndpoints() } @@ -143,17 +168,18 @@ func (ln *LocalNode) SetFallbackIP(ip net.IP) { ln.mu.Lock() defer ln.mu.Unlock() - ln.fallbackIP = ip + ln.endpointForIP(ip).fallbackIP = ip ln.updateEndpoints() } -// SetFallbackUDP sets the last-resort UDP port. This port is used +// SetFallbackUDP sets the last-resort UDP-on-IPv4 port. This port is used // if no endpoint prediction can be made. func (ln *LocalNode) SetFallbackUDP(port int) { ln.mu.Lock() defer ln.mu.Unlock() - ln.fallbackUDP = port + ln.endpoint4.fallbackUDP = port + ln.endpoint6.fallbackUDP = port ln.updateEndpoints() } @@ -163,7 +189,7 @@ func (ln *LocalNode) UDPEndpointStatement(fromaddr, endpoint *net.UDPAddr) { ln.mu.Lock() defer ln.mu.Unlock() - ln.udpTrack.AddStatement(fromaddr.String(), endpoint.String()) + ln.endpointForIP(endpoint.IP).track.AddStatement(fromaddr.String(), endpoint.String()) ln.updateEndpoints() } @@ -173,32 +199,50 @@ func (ln *LocalNode) UDPContact(toaddr *net.UDPAddr) { ln.mu.Lock() defer ln.mu.Unlock() - ln.udpTrack.AddContact(toaddr.String()) + ln.endpointForIP(toaddr.IP).track.AddContact(toaddr.String()) ln.updateEndpoints() } +// updateEndpoints updates the record with predicted endpoints. func (ln *LocalNode) updateEndpoints() { - // Determine the endpoints. - newIP := ln.fallbackIP - newUDP := ln.fallbackUDP - if ln.staticIP != nil { - newIP = ln.staticIP - } else if ip, port := predictAddr(ln.udpTrack); ip != nil { - newIP = ip - newUDP = port - } + ip4, udp4 := ln.endpoint4.get() + ip6, udp6 := ln.endpoint6.get() - // Update the record. - if newIP != nil && !newIP.IsUnspecified() { - ln.set(enr.IP(newIP)) - if newUDP != 0 { - ln.set(enr.UDP(newUDP)) - } else { - ln.delete(enr.UDP(0)) - } + if ip4 != nil && !ip4.IsUnspecified() { + ln.set(enr.IPv4(ip4)) } else { - ln.delete(enr.IP{}) + ln.delete(enr.IPv4{}) } + if ip6 != nil && !ip6.IsUnspecified() { + ln.set(enr.IPv6(ip6)) + } else { + ln.delete(enr.IPv6{}) + } + if udp4 != 0 { + ln.set(enr.UDP(udp4)) + } else { + ln.delete(enr.UDP(0)) + } + if udp6 != 0 && udp6 != udp4 { + ln.set(enr.UDP6(udp6)) + } else { + ln.delete(enr.UDP6(0)) + } +} + +// get returns the endpoint with highest precedence. +func (e *lnEndpoint) get() (newIP net.IP, newPort int) { + newPort = e.fallbackUDP + if e.fallbackIP != nil { + newIP = e.fallbackIP + } + if e.staticIP != nil { + newIP = e.staticIP + } else if ip, port := predictAddr(e.track); ip != nil { + newIP = ip + newPort = port + } + return newIP, newPort } // predictAddr wraps IPTracker.PredictEndpoint, converting from its string-based diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/node.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/node.go index b454ab255..9eb2544ff 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enode/node.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/node.go @@ -18,6 +18,7 @@ package enode import ( "crypto/ecdsa" + "encoding/base64" "encoding/hex" "errors" "fmt" @@ -27,8 +28,11 @@ import ( "strings" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/rlp" ) +var errMissingPrefix = errors.New("missing 'enr:' prefix for base64-encoded record") + // Node represents a host on the network. type Node struct { r enr.Record @@ -48,6 +52,34 @@ func New(validSchemes enr.IdentityScheme, r *enr.Record) (*Node, error) { return node, nil } +// MustParse parses a node record or enode:// URL. It panics if the input is invalid. +func MustParse(rawurl string) *Node { + n, err := Parse(ValidSchemes, rawurl) + if err != nil { + panic("invalid node: " + err.Error()) + } + return n +} + +// Parse decodes and verifies a base64-encoded node record. +func Parse(validSchemes enr.IdentityScheme, input string) (*Node, error) { + if strings.HasPrefix(input, "enode://") { + return ParseV4(input) + } + if !strings.HasPrefix(input, "enr:") { + return nil, errMissingPrefix + } + bin, err := base64.RawURLEncoding.DecodeString(input[4:]) + if err != nil { + return nil, err + } + var r enr.Record + if err := rlp.DecodeBytes(bin, &r); err != nil { + return nil, err + } + return New(validSchemes, &r) +} + // ID returns the node identifier. func (n *Node) ID() ID { return n.id @@ -68,11 +100,19 @@ func (n *Node) Load(k enr.Entry) error { return n.r.Load(k) } -// IP returns the IP address of the node. +// IP returns the IP address of the node. This prefers IPv4 addresses. func (n *Node) IP() net.IP { - var ip net.IP - n.Load((*enr.IP)(&ip)) - return ip + var ( + ip4 enr.IPv4 + ip6 enr.IPv6 + ) + if n.Load(&ip4) == nil { + return net.IP(ip4) + } + if n.Load(&ip6) == nil { + return net.IP(ip6) + } + return nil } // UDP returns the UDP port of the node. @@ -105,10 +145,11 @@ func (n *Node) Record() *enr.Record { return &cpy } -// checks whether n is a valid complete node. +// ValidateComplete checks whether n has a valid IP and UDP port. +// Deprecated: don't use this method. func (n *Node) ValidateComplete() error { if n.Incomplete() { - return errors.New("incomplete node") + return errors.New("missing IP address") } if n.UDP() == 0 { return errors.New("missing UDP port") @@ -122,20 +163,24 @@ func (n *Node) ValidateComplete() error { return n.Load(&key) } -// The string representation of a Node is a URL. -// Please see ParseNode for a description of the format. +// String returns the text representation of the record. func (n *Node) String() string { - return n.v4URL() + if isNewV4(n) { + return n.URLv4() // backwards-compatibility glue for NewV4 nodes + } + enc, _ := rlp.EncodeToBytes(&n.r) // always succeeds because record is valid + b64 := base64.RawURLEncoding.EncodeToString(enc) + return "enr:" + b64 } // MarshalText implements encoding.TextMarshaler. func (n *Node) MarshalText() ([]byte, error) { - return []byte(n.v4URL()), nil + return []byte(n.String()), nil } // UnmarshalText implements encoding.TextUnmarshaler. func (n *Node) UnmarshalText(text []byte) error { - dec, err := ParseV4(string(text)) + dec, err := Parse(ValidSchemes, string(text)) if err == nil { *n = *dec } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/nodedb.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/nodedb.go index 9353b155c..44332640c 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enode/nodedb.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/nodedb.go @@ -1,4 +1,4 @@ -// Copyright 2015 The go-ethereum Authors +// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ const ( const ( dbNodeExpiration = 24 * time.Hour // Time after which an unseen node should be dropped. dbCleanupCycle = time.Hour // Time period for running the expiration task. - dbVersion = 8 + dbVersion = 9 ) var zeroIP = make(net.IP, 16) @@ -380,12 +380,12 @@ func (db *DB) UpdateFindFails(id ID, ip net.IP, fails int) error { // LocalSeq retrieves the local record sequence counter. func (db *DB) localSeq(id ID) uint64 { - return db.fetchUint64(nodeItemKey(id, zeroIP, dbLocalSeq)) + return db.fetchUint64(localItemKey(id, dbLocalSeq)) } // storeLocalSeq stores the local record sequence counter. func (db *DB) storeLocalSeq(id ID, n uint64) { - db.storeUint64(nodeItemKey(id, zeroIP, dbLocalSeq), n) + db.storeUint64(localItemKey(id, dbLocalSeq), n) } // QuerySeeds retrieves random nodes to be used as potential seed nodes diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go b/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go index 50e9485d0..a9a3d1374 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enode/urlv4.go @@ -70,7 +70,7 @@ func ParseV4(rawurl string) (*Node, error) { if m := incompleteNodeURL.FindStringSubmatch(rawurl); m != nil { id, err := parsePubkey(m[1]) if err != nil { - return nil, fmt.Errorf("invalid node ID (%v)", err) + return nil, fmt.Errorf("invalid public key (%v)", err) } return NewV4(id, nil, 0, 0), nil } @@ -81,7 +81,7 @@ func ParseV4(rawurl string) (*Node, error) { // contained in the node has a zero-length signature. func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp int) *Node { var r enr.Record - if ip != nil { + if len(ip) > 0 { r.Set(enr.IP(ip)) } if udp != 0 { @@ -98,6 +98,12 @@ func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp int) *Node { return n } +// isNewV4 returns true for nodes created by NewV4. +func isNewV4(n *Node) bool { + var k s256raw + return n.r.IdentityScheme() == "" && n.r.Load(&k) == nil && len(n.r.Signature()) == 0 +} + func parseComplete(rawurl string) (*Node, error) { var ( id *ecdsa.PublicKey @@ -116,22 +122,20 @@ func parseComplete(rawurl string) (*Node, error) { return nil, errors.New("does not contain node ID") } if id, err = parsePubkey(u.User.String()); err != nil { - return nil, fmt.Errorf("invalid node ID (%v)", err) + return nil, fmt.Errorf("invalid public key (%v)", err) } // Parse the IP address. - host, port, err := net.SplitHostPort(u.Host) + ips, err := net.LookupIP(u.Hostname()) if err != nil { - return nil, fmt.Errorf("invalid host: %v", err) - } - if ip = net.ParseIP(host); ip == nil { - return nil, errors.New("invalid IP address") + return nil, err } + ip = ips[0] // Ensure the IP is 4 bytes long for IPv4 addresses. if ipv4 := ip.To4(); ipv4 != nil { ip = ipv4 } // Parse the port numbers. - if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil { + if tcpPort, err = strconv.ParseUint(u.Port(), 10, 16); err != nil { return nil, errors.New("invalid port") } udpPort = tcpPort @@ -157,7 +161,7 @@ func parsePubkey(in string) (*ecdsa.PublicKey, error) { return crypto.UnmarshalPubkey(b) } -func (n *Node) v4URL() string { +func (n *Node) URLv4() string { var ( scheme enr.ID nodeid string diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enr/enr.go b/vendor/github.com/ethereum/go-ethereum/p2p/enr/enr.go index 444820c15..c36ae9e3e 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enr/enr.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enr/enr.go @@ -163,6 +163,16 @@ func (r *Record) invalidate() { r.raw = nil } +// Signature returns the signature of the record. +func (r *Record) Signature() []byte { + if r.signature == nil { + return nil + } + cpy := make([]byte, len(r.signature)) + copy(cpy, r.signature) + return cpy +} + // EncodeRLP implements rlp.Encoder. Encoding fails if // the record is unsigned. func (r Record) EncodeRLP(w io.Writer) error { @@ -173,7 +183,7 @@ func (r Record) EncodeRLP(w io.Writer) error { return err } -// DecodeRLP implements rlp.Decoder. Decoding verifies the signature. +// DecodeRLP implements rlp.Decoder. Decoding doesn't verify the signature. func (r *Record) DecodeRLP(s *rlp.Stream) error { dec, raw, err := decodeRecord(s) if err != nil { diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/enr/entries.go b/vendor/github.com/ethereum/go-ethereum/p2p/enr/entries.go index 347990ab6..f2118401a 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/enr/entries.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/enr/entries.go @@ -60,11 +60,21 @@ type TCP uint16 func (v TCP) ENRKey() string { return "tcp" } +// UDP is the "udp" key, which holds the IPv6-specific UDP port of the node. +type TCP6 uint16 + +func (v TCP6) ENRKey() string { return "tcp6" } + // UDP is the "udp" key, which holds the UDP port of the node. type UDP uint16 func (v UDP) ENRKey() string { return "udp" } +// UDP is the "udp" key, which holds the IPv6-specific UDP port of the node. +type UDP6 uint16 + +func (v UDP6) ENRKey() string { return "udp6" } + // ID is the "id" key, which holds the name of the identity scheme. type ID string @@ -72,17 +82,27 @@ const IDv4 = ID("v4") // the default identity scheme func (v ID) ENRKey() string { return "id" } -// IP is the "ip" key, which holds the IP address of the node. +// IP is either the "ip" or "ip6" key, depending on the value. +// Use this value to encode IP addresses that can be either v4 or v6. +// To load an address from a record use the IPv4 or IPv6 types. type IP net.IP -func (v IP) ENRKey() string { return "ip" } +func (v IP) ENRKey() string { + if net.IP(v).To4() == nil { + return "ip6" + } + return "ip" +} // EncodeRLP implements rlp.Encoder. func (v IP) EncodeRLP(w io.Writer) error { if ip4 := net.IP(v).To4(); ip4 != nil { return rlp.Encode(w, ip4) } - return rlp.Encode(w, net.IP(v)) + if ip6 := net.IP(v).To16(); ip6 != nil { + return rlp.Encode(w, ip6) + } + return fmt.Errorf("invalid IP address: %v", net.IP(v)) } // DecodeRLP implements rlp.Decoder. @@ -96,6 +116,56 @@ func (v *IP) DecodeRLP(s *rlp.Stream) error { return nil } +// IPv4 is the "ip" key, which holds the IP address of the node. +type IPv4 net.IP + +func (v IPv4) ENRKey() string { return "ip" } + +// EncodeRLP implements rlp.Encoder. +func (v IPv4) EncodeRLP(w io.Writer) error { + ip4 := net.IP(v).To4() + if ip4 == nil { + return fmt.Errorf("invalid IPv4 address: %v", net.IP(v)) + } + return rlp.Encode(w, ip4) +} + +// DecodeRLP implements rlp.Decoder. +func (v *IPv4) DecodeRLP(s *rlp.Stream) error { + if err := s.Decode((*net.IP)(v)); err != nil { + return err + } + if len(*v) != 4 { + return fmt.Errorf("invalid IPv4 address, want 4 bytes: %v", *v) + } + return nil +} + +// IPv6 is the "ip6" key, which holds the IP address of the node. +type IPv6 net.IP + +func (v IPv6) ENRKey() string { return "ip6" } + +// EncodeRLP implements rlp.Encoder. +func (v IPv6) EncodeRLP(w io.Writer) error { + ip6 := net.IP(v).To16() + if ip6 == nil { + return fmt.Errorf("invalid IPv6 address: %v", net.IP(v)) + } + return rlp.Encode(w, ip6) +} + +// DecodeRLP implements rlp.Decoder. +func (v *IPv6) DecodeRLP(s *rlp.Stream) error { + if err := s.Decode((*net.IP)(v)); err != nil { + return err + } + if len(*v) != 16 { + return fmt.Errorf("invalid IPv6 address, want 16 bytes: %v", *v) + } + return nil +} + // KeyError is an error related to a key. type KeyError struct { Key string diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/message.go b/vendor/github.com/ethereum/go-ethereum/p2p/message.go index ac12666e4..b98773222 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/message.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/message.go @@ -169,7 +169,7 @@ type MsgPipeRW struct { closed *int32 } -// WriteMsg sends a messsage on the pipe. +// WriteMsg sends a message on the pipe. // It blocks until the receiver has consumed the message payload. func (p *MsgPipeRW) WriteMsg(msg Msg) error { if atomic.LoadInt32(p.closed) == 0 { @@ -252,19 +252,23 @@ func ExpectMsg(r MsgReader, code uint64, content interface{}) error { type msgEventer struct { MsgReadWriter - feed *event.Feed - peerID enode.ID - Protocol string + feed *event.Feed + peerID enode.ID + Protocol string + localAddress string + remoteAddress string } // newMsgEventer returns a msgEventer which sends message events to the given // feed -func newMsgEventer(rw MsgReadWriter, feed *event.Feed, peerID enode.ID, proto string) *msgEventer { +func newMsgEventer(rw MsgReadWriter, feed *event.Feed, peerID enode.ID, proto, remote, local string) *msgEventer { return &msgEventer{ MsgReadWriter: rw, feed: feed, peerID: peerID, Protocol: proto, + remoteAddress: remote, + localAddress: local, } } @@ -276,11 +280,13 @@ func (ev *msgEventer) ReadMsg() (Msg, error) { return msg, err } ev.feed.Send(&PeerEvent{ - Type: PeerEventTypeMsgRecv, - Peer: ev.peerID, - Protocol: ev.Protocol, - MsgCode: &msg.Code, - MsgSize: &msg.Size, + Type: PeerEventTypeMsgRecv, + Peer: ev.peerID, + Protocol: ev.Protocol, + MsgCode: &msg.Code, + MsgSize: &msg.Size, + LocalAddress: ev.localAddress, + RemoteAddress: ev.remoteAddress, }) return msg, nil } @@ -293,11 +299,13 @@ func (ev *msgEventer) WriteMsg(msg Msg) error { return err } ev.feed.Send(&PeerEvent{ - Type: PeerEventTypeMsgSend, - Peer: ev.peerID, - Protocol: ev.Protocol, - MsgCode: &msg.Code, - MsgSize: &msg.Size, + Type: PeerEventTypeMsgSend, + Peer: ev.peerID, + Protocol: ev.Protocol, + MsgCode: &msg.Code, + MsgSize: &msg.Size, + LocalAddress: ev.localAddress, + RemoteAddress: ev.remoteAddress, }) return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go b/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go index 8df82bb07..8b29efdcd 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/metrics.go @@ -25,18 +25,17 @@ import ( "sync/atomic" "time" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/p2p/enode" ) const ( - MetricsInboundConnects = "p2p/InboundConnects" // Name for the registered inbound connects meter - MetricsInboundTraffic = "p2p/InboundTraffic" // Name for the registered inbound traffic meter - MetricsOutboundConnects = "p2p/OutboundConnects" // Name for the registered outbound connects meter - MetricsOutboundTraffic = "p2p/OutboundTraffic" // Name for the registered outbound traffic meter + MetricsInboundTraffic = "p2p/ingress" // Name for the registered inbound traffic meter + MetricsOutboundTraffic = "p2p/egress" // Name for the registered outbound traffic meter + MetricsOutboundConnects = "p2p/dials" // Name for the registered outbound connects meter + MetricsInboundConnects = "p2p/serves" // Name for the registered inbound connects meter MeteredPeerLimit = 1024 // This amount of peers are individually metered ) @@ -46,6 +45,7 @@ var ( ingressTrafficMeter = metrics.NewRegisteredMeter(MetricsInboundTraffic, nil) // Meter metering the cumulative ingress traffic egressConnectMeter = metrics.NewRegisteredMeter(MetricsOutboundConnects, nil) // Meter counting the egress connections egressTrafficMeter = metrics.NewRegisteredMeter(MetricsOutboundTraffic, nil) // Meter metering the cumulative egress traffic + activePeerGauge = metrics.NewRegisteredGauge("p2p/peers", nil) // Gauge tracking the current peer count PeerIngressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsInboundTraffic+"/") // Registry containing the peer ingress PeerEgressRegistry = metrics.NewPrefixedChildRegistry(metrics.EphemeralRegistry, MetricsOutboundTraffic+"/") // Registry containing the peer egress @@ -124,6 +124,8 @@ func newMeteredConn(conn net.Conn, ingress bool, ip net.IP) net.Conn { } else { egressConnectMeter.Mark(1) } + activePeerGauge.Inc(1) + return &meteredConn{ Conn: conn, ip: ip, @@ -161,6 +163,7 @@ func (c *meteredConn) Write(b []byte) (n int, err error) { // the ingress and the egress traffic registries using the peer's IP and node ID, // also emits connect event. func (c *meteredConn) handshakeDone(id enode.ID) { + // TODO (kurkomisi): use the node URL instead of the pure node ID. (the String() method of *Node) if atomic.AddInt32(&meteredPeerCount, 1) >= MeteredPeerLimit { // Don't register the peer in the traffic registries. atomic.AddInt32(&meteredPeerCount, -1) @@ -197,6 +200,7 @@ func (c *meteredConn) Close() error { IP: c.ip, Elapsed: time.Since(c.connected), }) + activePeerGauge.Dec(1) return err } id := c.id @@ -208,6 +212,7 @@ func (c *meteredConn) Close() error { IP: c.ip, ID: id, }) + activePeerGauge.Dec(1) return err } ingress, egress := uint64(c.ingressMeter.Count()), uint64(c.egressMeter.Count()) @@ -228,5 +233,6 @@ func (c *meteredConn) Close() error { Ingress: ingress, Egress: egress, }) + activePeerGauge.Dec(1) return err } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/netutil/addrutil.go b/vendor/github.com/ethereum/go-ethereum/p2p/netutil/addrutil.go new file mode 100644 index 000000000..fb6d8d273 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/netutil/addrutil.go @@ -0,0 +1,33 @@ +// Copyright 2019 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 netutil + +import "net" + +// AddrIP gets the IP address contained in addr. It returns nil if no address is present. +func AddrIP(addr net.Addr) net.IP { + switch a := addr.(type) { + case *net.IPAddr: + return a.IP + case *net.TCPAddr: + return a.IP + case *net.UDPAddr: + return a.IP + default: + return nil + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/peer.go b/vendor/github.com/ethereum/go-ethereum/p2p/peer.go index 45567927b..372ba8d02 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/peer.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/peer.go @@ -91,12 +91,14 @@ const ( // PeerEvent is an event emitted when peers are either added or dropped from // a p2p.Server or when a message is sent or received on a peer connection type PeerEvent struct { - Type PeerEventType `json:"type"` - Peer enode.ID `json:"peer"` - Error string `json:"error,omitempty"` - Protocol string `json:"protocol,omitempty"` - MsgCode *uint64 `json:"msg_code,omitempty"` - MsgSize *uint32 `json:"msg_size,omitempty"` + Type PeerEventType `json:"type"` + Peer enode.ID `json:"peer"` + Error string `json:"error,omitempty"` + Protocol string `json:"protocol,omitempty"` + MsgCode *uint64 `json:"msg_code,omitempty"` + MsgSize *uint32 `json:"msg_size,omitempty"` + LocalAddress string `json:"local,omitempty"` + RemoteAddress string `json:"remote,omitempty"` } // Peer represents a connected remote node. @@ -120,7 +122,7 @@ func NewPeer(id enode.ID, name string, caps []Cap) *Peer { pipe, _ := net.Pipe() node := enode.SignNull(new(enr.Record), id) conn := &conn{fd: pipe, transport: nil, node: node, caps: caps, name: name} - peer := newPeer(conn, nil) + peer := newPeer(log.Root(), conn, nil) close(peer.closed) // ensures Disconnect doesn't block return peer } @@ -176,7 +178,7 @@ func (p *Peer) Inbound() bool { return p.rw.is(inboundConn) } -func newPeer(conn *conn, protocols []Protocol) *Peer { +func newPeer(log log.Logger, conn *conn, protocols []Protocol) *Peer { protomap := matchProtocols(protocols, conn.caps, conn) p := &Peer{ rw: conn, @@ -240,37 +242,10 @@ loop: close(p.closed) p.rw.close(reason) - - if shutdownErr := p.shutdownWithTimeout(5 * time.Second); shutdownErr != nil { - p.Log().Error("Timeout while waiting for the peer to shut down", "err", err) - } - + p.wg.Wait() return remoteRequested, err } -func (p *Peer) shutdownWithTimeout(timeout time.Duration) error { - /* A watchdog for the waitGroup (p.wg) - * When a peer shuts down we give 5 seconds for all protocols to finish, - * but we continue the process anyway (and print a warning message). - * Otherwise, this peer will be stuck in the list of peers (`admin_peers`) - * and won't be able to reconnect until the app is restarted. - * */ - c := make(chan struct{}) - - go func() { - p.wg.Wait() - close(c) - }() - - select { - case <-c: - p.Log().Debug("Peer stopped successfully") - return nil - case <-time.After(timeout): - return errors.New("WATCHDOG_ENGAGED. A few goroutines leaked.") - } -} - func (p *Peer) pingLoop() { ping := time.NewTimer(pingInterval) defer p.wg.Done() @@ -381,7 +356,7 @@ func (p *Peer) startProtocols(writeStart <-chan struct{}, writeErr chan<- error) proto.werr = writeErr var rw MsgReadWriter = proto if p.events != nil { - rw = newMsgEventer(rw, p.events, p.ID(), proto.Name) + rw = newMsgEventer(rw, p.events, p.ID(), proto.Name, p.Info().Network.RemoteAddress, p.Info().Network.LocalAddress) } p.log.Trace(fmt.Sprintf("Starting protocol %s/%d", proto.Name, proto.Version)) go func() { @@ -452,10 +427,11 @@ func (rw *protoRW) ReadMsg() (Msg, error) { // peer. Sub-protocol independent fields are contained and initialized here, with // protocol specifics delegated to all connected sub-protocols. type PeerInfo struct { - Enode string `json:"enode"` // Node URL - ID string `json:"id"` // Unique node identifier - Name string `json:"name"` // Name of the node, including client type, version, OS, custom data - Caps []string `json:"caps"` // Protocols advertised by this peer + ENR string `json:"enr,omitempty"` // Ethereum Node Record + Enode string `json:"enode"` // Node URL + ID string `json:"id"` // Unique node identifier + Name string `json:"name"` // Name of the node, including client type, version, OS, custom data + Caps []string `json:"caps"` // Protocols advertised by this peer Network struct { LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection @@ -475,12 +451,15 @@ func (p *Peer) Info() *PeerInfo { } // Assemble the generic peer metadata info := &PeerInfo{ - Enode: p.Node().String(), + Enode: p.Node().URLv4(), ID: p.ID().String(), Name: p.Name(), Caps: caps, Protocols: make(map[string]interface{}), } + if p.Node().Seq() > 0 { + info.ENR = p.Node().String() + } info.Network.LocalAddress = p.LocalAddr().String() info.Network.RemoteAddress = p.RemoteAddr().String() info.Network.Inbound = p.rw.is(inboundConn) diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go b/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go index 9438ab8e4..9ce4c2020 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/protocol.go @@ -79,5 +79,3 @@ func (cs capsByNameAndVersion) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] } func (cs capsByNameAndVersion) Less(i, j int) bool { return cs[i].Name < cs[j].Name || (cs[i].Name == cs[j].Name && cs[i].Version < cs[j].Version) } - -func (capsByNameAndVersion) ENRKey() string { return "cap" } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go b/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go index 67cc1d9bf..52e1eb8a4 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/rlpx.go @@ -38,7 +38,6 @@ import ( "github.com/ethereum/go-ethereum/common/bitutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" - "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/rlp" "github.com/golang/snappy" "golang.org/x/crypto/sha3" @@ -47,10 +46,10 @@ import ( const ( maxUint24 = ^uint32(0) >> 8 - sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 - sigLen = 65 // elliptic S256 - pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte - shaLen = 32 // hash length (for nonce etc) + sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 + sigLen = crypto.SignatureLength // elliptic S256 + pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte + shaLen = 32 // hash length (for nonce etc) authMsgLen = sigLen + shaLen + pubLen + shaLen + 1 authRespLen = pubLen + shaLen + 1 @@ -128,7 +127,7 @@ func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err // as the error so it can be tracked elsewhere. werr := make(chan error, 1) go func() { werr <- Send(t.rw, handshakeMsg, our) }() - if their, err = readProtocolHandshake(t.rw, our); err != nil { + if their, err = readProtocolHandshake(t.rw); err != nil { <-werr // make sure the write terminates too return nil, err } @@ -141,7 +140,7 @@ func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err return their, nil } -func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake, error) { +func readProtocolHandshake(rw MsgReader) (*protoHandshake, error) { msg, err := rw.ReadMsg() if err != nil { return nil, err @@ -400,7 +399,7 @@ func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) erro return err } signedMsg := xor(token, h.initNonce) - remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg.Signature[:]) + remoteRandomPub, err := crypto.Ecrecover(signedMsg, msg.Signature[:]) if err != nil { return err } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/server.go b/vendor/github.com/ethereum/go-ethereum/p2p/server.go index 2fbfe774f..121145fcc 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/server.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/server.go @@ -22,6 +22,7 @@ import ( "crypto/ecdsa" "encoding/hex" "errors" + "fmt" "net" "sort" "sync" @@ -39,7 +40,6 @@ import ( "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" - "github.com/ethereum/go-ethereum/rlp" ) const ( @@ -50,6 +50,9 @@ const ( defaultMaxPendingPeers = 50 defaultDialRatio = 3 + // This time limits inbound connection attempts per source IP. + inboundThrottleTime = 30 * time.Second + // Maximum time allowed for reading a complete message. // This is effectively the amount of time a connection can be idle. frameReadTimeout = 30 * time.Second @@ -159,6 +162,7 @@ type Server struct { // the whole protocol stack. newTransport func(net.Conn) transport newPeerHook func(*Peer) + listenFunc func(network, addr string) (net.Listener, error) lock sync.Mutex // protects running running bool @@ -168,24 +172,26 @@ type Server struct { ntab discoverTable listener net.Listener ourHandshake *protoHandshake - lastLookup time.Time DiscV5 *discv5.Network + loopWG sync.WaitGroup // loop, listenLoop + peerFeed event.Feed + log log.Logger - // These are for Peers, PeerCount (and nothing else). - peerOp chan peerOpFunc - peerOpDone chan struct{} + // Channels into the run loop. + quit chan struct{} + addstatic chan *enode.Node + removestatic chan *enode.Node + addtrusted chan *enode.Node + removetrusted chan *enode.Node + peerOp chan peerOpFunc + peerOpDone chan struct{} + delpeer chan peerDrop + checkpointPostHandshake chan *conn + checkpointAddPeer chan *conn - quit chan struct{} - addstatic chan *enode.Node - removestatic chan *enode.Node - addtrusted chan *enode.Node - removetrusted chan *enode.Node - posthandshake chan *conn - addpeer chan *conn - delpeer chan peerDrop - loopWG sync.WaitGroup // loop, listenLoop - peerFeed event.Feed - log log.Logger + // State of run loop and listenLoop. + lastLookup time.Time + inboundHistory expHeap } type peerOpFunc func(map[enode.ID]*Peer) @@ -280,6 +286,11 @@ func (c *conn) set(f connFlag, val bool) { } } +// LocalNode returns the local node record. +func (srv *Server) LocalNode() *enode.LocalNode { + return srv.localnode +} + // Peers returns all connected peers. func (srv *Server) Peers() []*Peer { var ps []*Peer @@ -446,7 +457,7 @@ func (srv *Server) Start() (err error) { srv.running = true srv.log = srv.Config.Logger if srv.log == nil { - srv.log = log.New() + srv.log = log.Root() } if srv.NoDial && srv.ListenAddr == "" { srv.log.Warn("P2P server will be useless, neither dialing nor listening") @@ -459,13 +470,16 @@ func (srv *Server) Start() (err error) { if srv.newTransport == nil { srv.newTransport = newRLPX } + if srv.listenFunc == nil { + srv.listenFunc = net.Listen + } if srv.Dialer == nil { srv.Dialer = TCPDialer{&net.Dialer{Timeout: defaultDialTimeout}} } srv.quit = make(chan struct{}) - srv.addpeer = make(chan *conn) srv.delpeer = make(chan peerDrop) - srv.posthandshake = make(chan *conn) + srv.checkpointPostHandshake = make(chan *conn) + srv.checkpointAddPeer = make(chan *conn) srv.addstatic = make(chan *enode.Node) srv.removestatic = make(chan *enode.Node) srv.addtrusted = make(chan *enode.Node) @@ -486,7 +500,7 @@ func (srv *Server) Start() (err error) { } dynPeers := srv.maxDialedConns() - dialer := newDialState(srv.localnode.ID(), srv.StaticNodes, srv.BootstrapNodes, srv.ntab, dynPeers, srv.NetRestrict) + dialer := newDialState(srv.localnode.ID(), srv.ntab, dynPeers, &srv.Config) srv.loopWG.Add(1) go srv.run(dialer) return nil @@ -509,7 +523,6 @@ func (srv *Server) setupLocalNode() error { srv.nodedb = db srv.localnode = enode.NewLocalNode(db, srv.PrivateKey) srv.localnode.SetFallbackIP(net.IP{127, 0, 0, 1}) - srv.localnode.Set(capsByNameAndVersion(srv.ourHandshake.Caps)) // TODO: check conflicts for _, p := range srv.Protocols { for _, e := range p.Attributes { @@ -572,6 +585,7 @@ func (srv *Server) setupDiscovery() error { NetRestrict: srv.NetRestrict, Bootnodes: srv.BootstrapNodes, Unhandled: unhandled, + Log: srv.log, } ntab, err := discover.ListenUDP(conn, srv.localnode, cfg) if err != nil { @@ -600,27 +614,28 @@ func (srv *Server) setupDiscovery() error { } func (srv *Server) setupListening() error { - // Launch the TCP listener. - listener, err := net.Listen("tcp", srv.ListenAddr) + // Launch the listener. + listener, err := srv.listenFunc("tcp", srv.ListenAddr) if err != nil { return err } - laddr := listener.Addr().(*net.TCPAddr) - srv.ListenAddr = laddr.String() srv.listener = listener - srv.localnode.Set(enr.TCP(laddr.Port)) + srv.ListenAddr = listener.Addr().String() + + // Update the local node record and map the TCP listening port if NAT is configured. + if tcp, ok := listener.Addr().(*net.TCPAddr); ok { + srv.localnode.Set(enr.TCP(tcp.Port)) + if !tcp.IP.IsLoopback() && srv.NAT != nil { + srv.loopWG.Add(1) + go func() { + nat.Map(srv.NAT, srv.quit, "tcp", tcp.Port, tcp.Port, "ethereum p2p") + srv.loopWG.Done() + }() + } + } srv.loopWG.Add(1) go srv.listenLoop() - - // Map the TCP listening port if NAT is configured. - if !laddr.IP.IsLoopback() && srv.NAT != nil { - srv.loopWG.Add(1) - go func() { - nat.Map(srv.NAT, srv.quit, "tcp", laddr.Port, laddr.Port, "ethereum p2p") - srv.loopWG.Done() - }() - } return nil } @@ -632,7 +647,7 @@ type dialer interface { } func (srv *Server) run(dialstate dialer) { - srv.log.Info("Started P2P networking", "self", srv.localnode.Node()) + srv.log.Info("Started P2P networking", "self", srv.localnode.Node().URLv4()) defer srv.loopWG.Done() defer srv.nodedb.Close() @@ -688,6 +703,7 @@ running: case <-srv.quit: // The server was stopped. Run the cleanup logic. break running + case n := <-srv.addstatic: // This channel is used by AddPeer to add to the // ephemeral static peer list. Add it to the dialer, @@ -695,6 +711,7 @@ running: srv.log.Trace("Adding static node", "node", n) dialstate.removeStatic(n) dialstate.addStatic(n) + case n := <-srv.removestatic: // This channel is used by RemovePeer to send a // disconnect request to a peer and begin the @@ -704,6 +721,7 @@ running: if p, ok := peers[n.ID()]; ok { p.Disconnect(DiscRequested) } + case n := <-srv.addtrusted: // This channel is used by AddTrustedPeer to add an enode // to the trusted node set. @@ -713,21 +731,23 @@ running: if p, ok := peers[n.ID()]; ok { p.rw.set(trustedConn, true) } + case n := <-srv.removetrusted: // This channel is used by RemoveTrustedPeer to remove an enode // from the trusted node set. srv.log.Trace("Removing trusted node", "node", n) - if _, ok := trusted[n.ID()]; ok { - delete(trusted, n.ID()) - } + delete(trusted, n.ID()) + // Unmark any already-connected peer as trusted if p, ok := peers[n.ID()]; ok { p.rw.set(trustedConn, false) } + case op := <-srv.peerOp: // This channel is used by Peers and PeerCount. op(peers) srv.peerOpDone <- struct{}{} + case t := <-taskdone: // A task got done. Tell dialstate about it so it // can update its state and remove it from the active @@ -735,7 +755,8 @@ running: srv.log.Trace("Dial task done", "task", t) dialstate.taskDone(t, time.Now()) delTask(t) - case c := <-srv.posthandshake: + + case c := <-srv.checkpointPostHandshake: // A connection has passed the encryption handshake so // the remote identity is known (but hasn't been verified yet). if trusted[c.node.ID()] { @@ -743,25 +764,22 @@ running: c.flags |= trustedConn } // TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them. - select { - case c.cont <- srv.encHandshakeChecks(peers, inboundCount, c): - case <-srv.quit: - break running - } - case c := <-srv.addpeer: + c.cont <- srv.postHandshakeChecks(peers, inboundCount, c) + + case c := <-srv.checkpointAddPeer: // At this point the connection is past the protocol handshake. // Its capabilities are known and the remote identity is verified. - err := srv.protoHandshakeChecks(peers, inboundCount, c) + err := srv.addPeerChecks(peers, inboundCount, c) if err == nil { // The handshakes are done and it passed all checks. - p := newPeer(c, srv.Protocols) + p := newPeer(srv.log, c, srv.Protocols) // If message events are enabled, pass the peerFeed // to the peer if srv.EnableMsgEvents { p.events = &srv.peerFeed } name := truncateName(c.name) - srv.log.Debug("Adding p2p peer", "name", name, "addr", c.fd.RemoteAddr(), "peers", len(peers)+1) + p.log.Debug("Adding p2p peer", "addr", p.RemoteAddr(), "peers", len(peers)+1, "name", name) go srv.runPeer(p) peers[c.node.ID()] = p if p.Inbound() { @@ -771,15 +789,12 @@ running: // The dialer logic relies on the assumption that // dial tasks complete after the peer has been added or // discarded. Unblock the task last. - select { - case c.cont <- err: - case <-srv.quit: - break running - } + c.cont <- err + case pd := <-srv.delpeer: // A peer disconnected. d := common.PrettyDuration(mclock.Now() - pd.created) - pd.log.Debug("Removing p2p peer", "duration", d, "peers", len(peers)-1, "req", pd.requested, "err", pd.err) + pd.log.Debug("Removing p2p peer", "addr", pd.RemoteAddr(), "peers", len(peers)-1, "duration", d, "req", pd.requested, "err", pd.err) delete(peers, pd.ID()) if pd.Inbound() { inboundCount-- @@ -810,17 +825,7 @@ running: } } -func (srv *Server) protoHandshakeChecks(peers map[enode.ID]*Peer, inboundCount int, c *conn) error { - // Drop connections with no matching protocols. - if len(srv.Protocols) > 0 && countMatchingProtocols(srv.Protocols, c.caps) == 0 { - return DiscUselessPeer - } - // Repeat the encryption handshake checks because the - // peer set might have changed between the handshakes. - return srv.encHandshakeChecks(peers, inboundCount, c) -} - -func (srv *Server) encHandshakeChecks(peers map[enode.ID]*Peer, inboundCount int, c *conn) error { +func (srv *Server) postHandshakeChecks(peers map[enode.ID]*Peer, inboundCount int, c *conn) error { switch { case !c.is(trustedConn|staticDialedConn) && len(peers) >= srv.MaxPeers: return DiscTooManyPeers @@ -835,9 +840,20 @@ func (srv *Server) encHandshakeChecks(peers map[enode.ID]*Peer, inboundCount int } } +func (srv *Server) addPeerChecks(peers map[enode.ID]*Peer, inboundCount int, c *conn) error { + // Drop connections with no matching protocols. + if len(srv.Protocols) > 0 && countMatchingProtocols(srv.Protocols, c.caps) == 0 { + return DiscUselessPeer + } + // Repeat the post-handshake checks because the + // peer set might have changed since those checks were performed. + return srv.postHandshakeChecks(peers, inboundCount, c) +} + func (srv *Server) maxInboundConns() int { return srv.MaxPeers - srv.maxDialedConns() } + func (srv *Server) maxDialedConns() int { if srv.NoDiscovery || srv.NoDial { return 0 @@ -865,7 +881,7 @@ func (srv *Server) listenLoop() { } for { - // Wait for a handshake slot before accepting. + // Wait for a free slot before accepting. <-slots var ( @@ -884,21 +900,16 @@ func (srv *Server) listenLoop() { break } - // Reject connections that do not match NetRestrict. - if srv.NetRestrict != nil { - if tcp, ok := fd.RemoteAddr().(*net.TCPAddr); ok && !srv.NetRestrict.Contains(tcp.IP) { - srv.log.Debug("Rejected conn (not whitelisted in NetRestrict)", "addr", fd.RemoteAddr()) - fd.Close() - slots <- struct{}{} - continue - } + remoteIP := netutil.AddrIP(fd.RemoteAddr()) + if err := srv.checkInboundConn(fd, remoteIP); err != nil { + srv.log.Debug("Rejected inbound connnection", "addr", fd.RemoteAddr(), "err", err) + fd.Close() + slots <- struct{}{} + continue } - - var ip net.IP - if tcp, ok := fd.RemoteAddr().(*net.TCPAddr); ok { - ip = tcp.IP + if remoteIP != nil { + fd = newMeteredConn(fd, true, remoteIP) } - fd = newMeteredConn(fd, true, ip) srv.log.Trace("Accepted connection", "addr", fd.RemoteAddr()) go func() { srv.SetupConn(fd, inboundConn, nil) @@ -907,6 +918,22 @@ func (srv *Server) listenLoop() { } } +func (srv *Server) checkInboundConn(fd net.Conn, remoteIP net.IP) error { + if remoteIP != nil { + // Reject connections that do not match NetRestrict. + if srv.NetRestrict != nil && !srv.NetRestrict.Contains(remoteIP) { + return fmt.Errorf("not whitelisted in NetRestrict") + } + // Reject Internet peers that try too often. + srv.inboundHistory.expire(time.Now()) + if !netutil.IsLAN(remoteIP) && srv.inboundHistory.contains(remoteIP.String()) { + return fmt.Errorf("too many attempts") + } + srv.inboundHistory.add(remoteIP.String(), time.Now().Add(inboundThrottleTime)) + } + return nil +} + // SetupConn runs the handshakes and attempts to add the connection // as a peer. It returns when the connection has been added as a peer // or the handshakes have failed. @@ -928,6 +955,7 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro if !running { return errServerStopped } + // If dialing, figure out the remote public key. var dialPubkey *ecdsa.PublicKey if dialDest != nil { @@ -936,7 +964,8 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro return errors.New("dial destination doesn't have a secp256k1 public key") } } - // Run the encryption handshake. + + // Run the RLPx handshake. remotePubkey, err := c.doEncHandshake(srv.PrivateKey, dialPubkey) if err != nil { srv.log.Trace("Failed RLPx handshake", "addr", c.fd.RemoteAddr(), "conn", c.flags, "err", err) @@ -955,12 +984,13 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro conn.handshakeDone(c.node.ID()) } clog := srv.log.New("id", c.node.ID(), "addr", c.fd.RemoteAddr(), "conn", c.flags) - err = srv.checkpoint(c, srv.posthandshake) + err = srv.checkpoint(c, srv.checkpointPostHandshake) if err != nil { - clog.Trace("Rejected peer before protocol handshake", "err", err) + clog.Trace("Rejected peer", "err", err) return err } - // Run the protocol handshake + + // Run the capability negotiation handshake. phs, err := c.doProtoHandshake(srv.ourHandshake) if err != nil { clog.Trace("Failed proto handshake", "err", err) @@ -971,14 +1001,15 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro return DiscUnexpectedIdentity } c.caps, c.name = phs.Caps, phs.Name - err = srv.checkpoint(c, srv.addpeer) + err = srv.checkpoint(c, srv.checkpointAddPeer) if err != nil { clog.Trace("Rejected peer", "err", err) return err } - // If the checks completed successfully, runPeer has now been - // launched by run. - clog.Trace("connection set up", "inbound", dialDest == nil) + + // If the checks completed successfully, the connection has been added as a peer and + // runPeer has been launched. + clog.Trace("Connection set up", "inbound", dialDest == nil) return nil } @@ -1007,12 +1038,7 @@ func (srv *Server) checkpoint(c *conn, stage chan<- *conn) error { case <-srv.quit: return errServerStopped } - select { - case err := <-c.cont: - return err - case <-srv.quit: - return errServerStopped - } + return <-c.cont } // runPeer runs in its own goroutine for each peer. @@ -1025,8 +1051,10 @@ func (srv *Server) runPeer(p *Peer) { // broadcast peer add srv.peerFeed.Send(&PeerEvent{ - Type: PeerEventTypeAdd, - Peer: p.ID(), + Type: PeerEventTypeAdd, + Peer: p.ID(), + RemoteAddress: p.RemoteAddr().String(), + LocalAddress: p.LocalAddr().String(), }) // run the protocol @@ -1034,9 +1062,11 @@ func (srv *Server) runPeer(p *Peer) { // broadcast peer drop srv.peerFeed.Send(&PeerEvent{ - Type: PeerEventTypeDrop, - Peer: p.ID(), - Error: err.Error(), + Type: PeerEventTypeDrop, + Peer: p.ID(), + Error: err.Error(), + RemoteAddress: p.RemoteAddr().String(), + LocalAddress: p.LocalAddr().String(), }) // Note: run waits for existing peers to be sent on srv.delpeer @@ -1065,7 +1095,7 @@ func (srv *Server) NodeInfo() *NodeInfo { node := srv.Self() info := &NodeInfo{ Name: srv.Name, - Enode: node.String(), + Enode: node.URLv4(), ID: node.ID().String(), IP: node.IP().String(), ListenAddr: srv.ListenAddr, @@ -1073,9 +1103,7 @@ func (srv *Server) NodeInfo() *NodeInfo { } info.Ports.Discovery = node.UDP() info.Ports.Listener = node.TCP() - if enc, err := rlp.EncodeToBytes(node.Record()); err == nil { - info.ENR = "0x" + hex.EncodeToString(enc) - } + info.ENR = node.String() // Gather all the running protocol infos (only once per protocol type) for _, proto := range srv.Protocols { diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/util.go b/vendor/github.com/ethereum/go-ethereum/p2p/util.go new file mode 100644 index 000000000..2a6edf5ce --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/util.go @@ -0,0 +1,82 @@ +// Copyright 2019 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 p2p + +import ( + "container/heap" + "time" +) + +// expHeap tracks strings and their expiry time. +type expHeap []expItem + +// expItem is an entry in addrHistory. +type expItem struct { + item string + exp time.Time +} + +// nextExpiry returns the next expiry time. +func (h *expHeap) nextExpiry() time.Time { + return (*h)[0].exp +} + +// add adds an item and sets its expiry time. +func (h *expHeap) add(item string, exp time.Time) { + heap.Push(h, expItem{item, exp}) +} + +// remove removes an item. +func (h *expHeap) remove(item string) bool { + for i, v := range *h { + if v.item == item { + heap.Remove(h, i) + return true + } + } + return false +} + +// contains checks whether an item is present. +func (h expHeap) contains(item string) bool { + for _, v := range h { + if v.item == item { + return true + } + } + return false +} + +// expire removes items with expiry time before 'now'. +func (h *expHeap) expire(now time.Time) { + for h.Len() > 0 && h.nextExpiry().Before(now) { + heap.Pop(h) + } +} + +// heap.Interface boilerplate +func (h expHeap) Len() int { return len(h) } +func (h expHeap) Less(i, j int) bool { return h[i].exp.Before(h[j].exp) } +func (h expHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *expHeap) Push(x interface{}) { *h = append(*h, x.(expItem)) } +func (h *expHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} diff --git a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go index bdaa4a18c..36f13d178 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go +++ b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go @@ -20,6 +20,16 @@ package params // the main Ethereum network. var MainnetBootnodes = []string{ // Ethereum Foundation Go Bootnodes + "enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", // bootnode-aws-ap-southeast-1-001 + "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", // bootnode-aws-us-east-1-001 + "enode://ca6de62fce278f96aea6ec5a2daadb877e51651247cb96ee310a318def462913b653963c155a0ef6c7d50048bba6e6cea881130857413d9f50a621546b590758@34.255.23.113:30303", // bootnode-aws-eu-west-1-001 + "enode://279944d8dcd428dffaa7436f25ca0ca43ae19e7bcf94a8fb7d1641651f92d121e972ac2e8f381414b80cc8e5555811c2ec6e1a99bb009b3f53c4c69923e11bd8@35.158.244.151:30303", // bootnode-aws-eu-central-1-001 + "enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303", // bootnode-azure-australiaeast-001 + "enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303", // bootnode-azure-brazilsouth-001 + "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", // bootnode-azure-koreasouth-001 + "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", // bootnode-azure-westus-001 + + // Ethereum Foundation Go Bootnodes (legacy) "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", // IE "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", // US-WEST "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", // BR @@ -50,7 +60,7 @@ var RinkebyBootnodes = []string{ // GoerliBootnodes are the enode URLs of the P2P bootstrap nodes running on the // Görli test network. var GoerliBootnodes = []string{ - // Upstrem bootnodes + // Upstream bootnodes "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", diff --git a/vendor/github.com/ethereum/go-ethereum/params/config.go b/vendor/github.com/ethereum/go-ethereum/params/config.go index c59c748ac..a40048524 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/config.go +++ b/vendor/github.com/ethereum/go-ethereum/params/config.go @@ -17,10 +17,12 @@ package params import ( + "encoding/binary" "fmt" "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) // Genesis hashes to enforce below configs on. @@ -40,6 +42,15 @@ var TrustedCheckpoints = map[common.Hash]*TrustedCheckpoint{ GoerliGenesisHash: GoerliTrustedCheckpoint, } +// CheckpointOracles associates each known checkpoint oracles with the genesis hash of +// the chain it belongs to. +var CheckpointOracles = map[common.Hash]*CheckpointOracleConfig{ + MainnetGenesisHash: MainnetCheckpointOracle, + TestnetGenesisHash: TestnetCheckpointOracle, + RinkebyGenesisHash: RinkebyCheckpointOracle, + GoerliGenesisHash: GoerliCheckpointOracle, +} + var ( // MainnetChainConfig is the chain parameters to run a node on the main network. MainnetChainConfig = &ChainConfig{ @@ -54,16 +65,29 @@ var ( ByzantiumBlock: big.NewInt(4370000), ConstantinopleBlock: big.NewInt(7280000), PetersburgBlock: big.NewInt(7280000), + IstanbulBlock: nil, Ethash: new(EthashConfig), } // MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network. MainnetTrustedCheckpoint = &TrustedCheckpoint{ - Name: "mainnet", - SectionIndex: 227, - SectionHead: common.HexToHash("0xa2e0b25d72c2fc6e35a7f853cdacb193b4b4f95c606accf7f8fa8415283582c7"), - CHTRoot: common.HexToHash("0xf69bdd4053b95b61a27b106a0e86103d791edd8574950dc96aa351ab9b9f1aa0"), - BloomRoot: common.HexToHash("0xec1b454d4c6322c78ccedf76ac922a8698c3cac4d98748a84af4995b7bd3d744"), + SectionIndex: 260, + SectionHead: common.HexToHash("0x613fc3c65f2abe9d66564c2d1f7c7600cd51a90a26bd9c0fda1ad9c6739428eb"), + CHTRoot: common.HexToHash("0x2a81a659f524be86929e4d34e4da05c024a68c9f44bd1184eae303802baa121e"), + BloomRoot: common.HexToHash("0x7718ec4b9ce11365b98063dc90808a87c7c1dc14c76e418a2a64a717688a601d"), + } + + // MainnetCheckpointOracle contains a set of configs for the main network oracle. + MainnetCheckpointOracle = &CheckpointOracleConfig{ + Address: common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), + Signers: []common.Address{ + common.HexToAddress("0x1b2C260efc720BE89101890E4Db589b44E950527"), // Peter + common.HexToAddress("0x78d1aD571A1A09D60D9BBf25894b44e4C8859595"), // Martin + common.HexToAddress("0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7"), // Zsolt + common.HexToAddress("0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E"), // Gary + common.HexToAddress("0x0DF8fa387C602AE62559cC4aFa4972A7045d6707"), // Guillaume + }, + Threshold: 2, } // TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network. @@ -79,16 +103,29 @@ var ( ByzantiumBlock: big.NewInt(1700000), ConstantinopleBlock: big.NewInt(4230000), PetersburgBlock: big.NewInt(4939394), + IstanbulBlock: big.NewInt(6485846), Ethash: new(EthashConfig), } // TestnetTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network. TestnetTrustedCheckpoint = &TrustedCheckpoint{ - Name: "testnet", - SectionIndex: 161, - SectionHead: common.HexToHash("0x5378afa734e1feafb34bcca1534c4d96952b754579b96a4afb23d5301ecececc"), - CHTRoot: common.HexToHash("0x1cf2b071e7443a62914362486b613ff30f60cea0d9c268ed8c545f876a3ee60c"), - BloomRoot: common.HexToHash("0x5ac25c84bd18a9cbe878d4609a80220f57f85037a112644532412ba0d498a31b"), + SectionIndex: 194, + SectionHead: common.HexToHash("0x34b61d0b77bbbbc7747db9a786e5ac976a83ec0c7c0238d319ec95243754cfcc"), + CHTRoot: common.HexToHash("0x6793d6efd08e5f17074f5cfe3f32cc552a7514d967d03ea253b0c1cefec68f00"), + BloomRoot: common.HexToHash("0x07570f99a7d5dcdc95c40ec9145b65ecbda0c4e61f9f99fa9eff39d91a4d8ad5"), + } + + // TestnetCheckpointOracle contains a set of configs for the Ropsten test network oracle. + TestnetCheckpointOracle = &CheckpointOracleConfig{ + Address: common.HexToAddress("0xEF79475013f154E6A65b54cB2742867791bf0B84"), + Signers: []common.Address{ + common.HexToAddress("0x32162F3581E88a5f62e8A61892B42C46E2c18f7b"), // Peter + common.HexToAddress("0x78d1aD571A1A09D60D9BBf25894b44e4C8859595"), // Martin + common.HexToAddress("0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7"), // Zsolt + common.HexToAddress("0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E"), // Gary + common.HexToAddress("0x0DF8fa387C602AE62559cC4aFa4972A7045d6707"), // Guillaume + }, + Threshold: 2, } // RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network. @@ -104,6 +141,7 @@ var ( ByzantiumBlock: big.NewInt(1035301), ConstantinopleBlock: big.NewInt(3660663), PetersburgBlock: big.NewInt(4321234), + IstanbulBlock: big.NewInt(5435345), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -112,11 +150,22 @@ var ( // RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network. RinkebyTrustedCheckpoint = &TrustedCheckpoint{ - Name: "rinkeby", - SectionIndex: 125, - SectionHead: common.HexToHash("0x8a738386f6bb34add15846f8f49c4c519a2f32519096e792b9f43bcb407c831c"), - CHTRoot: common.HexToHash("0xa1e5720a9bad4dce794f129e4ac6744398197b652868011486a6f89c8ec84a75"), - BloomRoot: common.HexToHash("0xa3048fe8b7e30f77f11bc755a88478363d7d3e71c2bdfe4e8ab9e269cd804ba2"), + SectionIndex: 155, + SectionHead: common.HexToHash("0x746df19e755fa6310ce3b00bb29229d590aa80002012e64ef648010b8b63db67"), + CHTRoot: common.HexToHash("0xc6a1093d82003141feb1052a96e0c95cea62d64c230f805d7835857d321c0c1a"), + BloomRoot: common.HexToHash("0x9d0fc2ea21c5850a9bceb73a82a405e9934788f56a5d20f81b0bb417497a9f92"), + } + + // RinkebyCheckpointOracle contains a set of configs for the Rinkeby test network oracle. + RinkebyCheckpointOracle = &CheckpointOracleConfig{ + Address: common.HexToAddress("0xebe8eFA441B9302A0d7eaECc277c09d20D684540"), + Signers: []common.Address{ + common.HexToAddress("0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3"), // Peter + common.HexToAddress("0x78d1aD571A1A09D60D9BBf25894b44e4C8859595"), // Martin + common.HexToAddress("0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7"), // Zsolt + common.HexToAddress("0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E"), // Gary + }, + Threshold: 2, } // GoerliChainConfig contains the chain parameters to run a node on the Görli test network. @@ -131,6 +180,7 @@ var ( ByzantiumBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(1561651), Clique: &CliqueConfig{ Period: 15, Epoch: 30000, @@ -139,11 +189,23 @@ var ( // GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network. GoerliTrustedCheckpoint = &TrustedCheckpoint{ - Name: "goerli", - SectionIndex: 9, - SectionHead: common.HexToHash("0x8e223d827391eee53b07cb8ee057dbfa11c93e0b45352188c783affd7840a921"), - CHTRoot: common.HexToHash("0xe0a817ac69b36c1e437c5b0cff9e764853f5115702b5f66d451b665d6afb7e78"), - BloomRoot: common.HexToHash("0x50d672aeb655b723284969c7c1201fb6ca003c23ed144bcb9f2d1b30e2971c1b"), + SectionIndex: 39, + SectionHead: common.HexToHash("0x512b5c1533d6faa3b968f095e61ad96007fda91ea296af433d96045580d9c140"), + CHTRoot: common.HexToHash("0x1a8e8ffd2cae5de61c2d06a686944b7809064ce38109c0e3ca203b5ed363bb0e"), + BloomRoot: common.HexToHash("0x32a3fec7d590143b0ccc4f1bb9fc1d9e03a30894e625a1d44d5be60e7b932491"), + } + + // GoerliCheckpointOracle contains a set of configs for the Goerli test network oracle. + GoerliCheckpointOracle = &CheckpointOracleConfig{ + Address: common.HexToAddress("0x18CA0E045F0D772a851BC7e48357Bcaab0a0795D"), + Signers: []common.Address{ + common.HexToAddress("0x4769bcaD07e3b938B7f43EB7D278Bc7Cb9efFb38"), // Peter + common.HexToAddress("0x78d1aD571A1A09D60D9BBf25894b44e4C8859595"), // Martin + common.HexToAddress("0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7"), // Zsolt + common.HexToAddress("0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E"), // Gary + common.HexToAddress("0x0DF8fa387C602AE62559cC4aFa4972A7045d6707"), // Guillaume + }, + Threshold: 2, } // AllEthashProtocolChanges contains every protocol change (EIPs) introduced @@ -151,16 +213,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -169,13 +231,43 @@ var ( // used to start light syncing from this checkpoint and avoid downloading the // entire header chain while still being able to securely access old headers/logs. type TrustedCheckpoint struct { - Name string `json:"-"` SectionIndex uint64 `json:"sectionIndex"` SectionHead common.Hash `json:"sectionHead"` CHTRoot common.Hash `json:"chtRoot"` BloomRoot common.Hash `json:"bloomRoot"` } +// HashEqual returns an indicator comparing the itself hash with given one. +func (c *TrustedCheckpoint) HashEqual(hash common.Hash) bool { + if c.Empty() { + return hash == common.Hash{} + } + return c.Hash() == hash +} + +// Hash returns the hash of checkpoint's four key fields(index, sectionHead, chtRoot and bloomTrieRoot). +func (c *TrustedCheckpoint) Hash() common.Hash { + buf := make([]byte, 8+3*common.HashLength) + binary.BigEndian.PutUint64(buf, c.SectionIndex) + copy(buf[8:], c.SectionHead.Bytes()) + copy(buf[8+common.HashLength:], c.CHTRoot.Bytes()) + copy(buf[8+2*common.HashLength:], c.BloomRoot.Bytes()) + return crypto.Keccak256Hash(buf) +} + +// Empty returns an indicator whether the checkpoint is regarded as empty. +func (c *TrustedCheckpoint) Empty() bool { + return c.SectionHead == (common.Hash{}) || c.CHTRoot == (common.Hash{}) || c.BloomRoot == (common.Hash{}) +} + +// CheckpointOracleConfig represents a set of checkpoint contract(which acts as an oracle) +// config which used for light client checkpoint syncing. +type CheckpointOracleConfig struct { + Address common.Address `json:"address"` + Signers []common.Address `json:"signers"` + Threshold uint64 `json:"threshold"` +} + // ChainConfig is the core config which determines the blockchain settings. // // ChainConfig is stored in the database on a per block basis. This means @@ -199,6 +291,7 @@ type ChainConfig struct { ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) + IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul) EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated) // Various consensus engines @@ -236,7 +329,7 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v ConstantinopleFix: %v Engine: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v Engine: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -247,6 +340,7 @@ func (c *ChainConfig) String() string { c.ByzantiumBlock, c.ConstantinopleBlock, c.PetersburgBlock, + c.IstanbulBlock, engine, ) } @@ -293,30 +387,16 @@ func (c *ChainConfig) IsPetersburg(num *big.Int) bool { return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num) } +// IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. +func (c *ChainConfig) IsIstanbul(num *big.Int) bool { + return isForked(c.IstanbulBlock, num) +} + // IsEWASM returns whether num represents a block number after the EWASM fork func (c *ChainConfig) IsEWASM(num *big.Int) bool { return isForked(c.EWASMBlock, num) } -// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice). -// -// The returned GasTable's fields shouldn't, under any circumstances, be changed. -func (c *ChainConfig) GasTable(num *big.Int) GasTable { - if num == nil { - return GasTableHomestead - } - switch { - case c.IsConstantinople(num): - return GasTableConstantinople - case c.IsEIP158(num): - return GasTableEIP158 - case c.IsEIP150(num): - return GasTableEIP150 - default: - return GasTableHomestead - } -} - // CheckCompatible checks whether scheduled fork transitions have been imported // with a mismatching chain configuration. func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { @@ -364,7 +444,10 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock) } if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) { - return newCompatError("ConstantinopleFix fork block", c.PetersburgBlock, newcfg.PetersburgBlock) + return newCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock) + } + if isForkIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) { + return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock) } if isForkIncompatible(c.EWASMBlock, newcfg.EWASMBlock, head) { return newCompatError("ewasm fork block", c.EWASMBlock, newcfg.EWASMBlock) @@ -433,9 +516,9 @@ func (err *ConfigCompatError) Error() string { // Rules is a one time interface meaning that it shouldn't be used in between transition // phases. type Rules struct { - ChainID *big.Int - IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool - IsByzantium, IsConstantinople, IsPetersburg bool + ChainID *big.Int + IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool + IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool } // Rules ensures c's ChainID is not nil. @@ -453,5 +536,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsByzantium: c.IsByzantium(num), IsConstantinople: c.IsConstantinople(num), IsPetersburg: c.IsPetersburg(num), + IsIstanbul: c.IsIstanbul(num), } } diff --git a/vendor/github.com/ethereum/go-ethereum/params/gas_table.go b/vendor/github.com/ethereum/go-ethereum/params/gas_table.go deleted file mode 100644 index 6c4a38269..000000000 --- a/vendor/github.com/ethereum/go-ethereum/params/gas_table.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package params - -// GasTable organizes gas prices for different ethereum phases. -type GasTable struct { - ExtcodeSize uint64 - ExtcodeCopy uint64 - ExtcodeHash uint64 - Balance uint64 - SLoad uint64 - Calls uint64 - Suicide uint64 - - ExpByte uint64 - - // CreateBySuicide occurs when the - // refunded account is one that does - // not exist. This logic is similar - // to call. May be left nil. Nil means - // not charged. - CreateBySuicide uint64 -} - -// Variables containing gas prices for different ethereum phases. -var ( - // GasTableHomestead contain the gas prices for - // the homestead phase. - GasTableHomestead = GasTable{ - ExtcodeSize: 20, - ExtcodeCopy: 20, - Balance: 20, - SLoad: 50, - Calls: 40, - Suicide: 0, - ExpByte: 10, - } - - // GasTableEIP150 contain the gas re-prices for - // the EIP150 phase. - GasTableEIP150 = GasTable{ - ExtcodeSize: 700, - ExtcodeCopy: 700, - Balance: 400, - SLoad: 200, - Calls: 700, - Suicide: 5000, - ExpByte: 10, - - CreateBySuicide: 25000, - } - // GasTableEIP158 contain the gas re-prices for - // the EIP155/EIP158 phase. - GasTableEIP158 = GasTable{ - ExtcodeSize: 700, - ExtcodeCopy: 700, - Balance: 400, - SLoad: 200, - Calls: 700, - Suicide: 5000, - ExpByte: 50, - - CreateBySuicide: 25000, - } - // GasTableConstantinople contain the gas re-prices for - // the constantinople phase. - GasTableConstantinople = GasTable{ - ExtcodeSize: 700, - ExtcodeCopy: 700, - ExtcodeHash: 400, - Balance: 400, - SLoad: 200, - Calls: 700, - Suicide: 5000, - ExpByte: 50, - - CreateBySuicide: 25000, - } -) diff --git a/vendor/github.com/ethereum/go-ethereum/params/network_params.go b/vendor/github.com/ethereum/go-ethereum/params/network_params.go index f8731e897..bba24721c 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/network_params.go +++ b/vendor/github.com/ethereum/go-ethereum/params/network_params.go @@ -32,13 +32,8 @@ const ( // considered probably final and its rotated bits are calculated. BloomConfirms = 256 - // CHTFrequencyClient is the block frequency for creating CHTs on the client side. - CHTFrequencyClient = 32768 - - // CHTFrequencyServer is the block frequency for creating CHTs on the server side. - // Eventually this can be merged back with the client version, but that requires a - // full database upgrade, so that should be left for a suitable moment. - CHTFrequencyServer = 4096 + // CHTFrequency is the block frequency for creating CHTs + CHTFrequency = 32768 // BloomTrieFrequency is the block frequency for creating BloomTrie on both // server/client sides. @@ -51,4 +46,16 @@ const ( // HelperTrieProcessConfirmations is the number of confirmations before a HelperTrie // is generated HelperTrieProcessConfirmations = 256 + + // CheckpointFrequency is the block frequency for creating checkpoint + CheckpointFrequency = 32768 + + // CheckpointProcessConfirmations is the number before a checkpoint is generated + CheckpointProcessConfirmations = 256 + + // ImmutabilityThreshold is the number of blocks after which a chain segment is + // considered immutable (i.e. soft finality). It is used by the downloader as a + // hard limit against deep ancestors, by the blockchain against deep reorgs, by + // the freezer as the cutoff treshold and by clique as the snapshot trust limit. + ImmutabilityThreshold = 90000 ) diff --git a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go index c8b6609af..11b858a61 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go +++ b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go @@ -52,39 +52,83 @@ const ( NetSstoreResetRefund uint64 = 4800 // Once per SSTORE operation for resetting to the original non-zero value NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value - JumpdestGas uint64 = 1 // Refunded gas, once per SSTORE operation if the zeroness changes to zero. - EpochDuration uint64 = 30000 // Duration between proof-of-work epochs. - CallGas uint64 = 40 // Once per CALL operation & message call transaction. - CreateDataGas uint64 = 200 // - CallCreateDepth uint64 = 1024 // Maximum depth of call/create stack. - ExpGas uint64 = 10 // Once per EXP instruction - LogGas uint64 = 375 // Per LOG* operation. - CopyGas uint64 = 3 // - StackLimit uint64 = 1024 // Maximum size of VM stack allowed. - TierStepGas uint64 = 0 // Once per operation, for a selection of them. - LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. - CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction. - Create2Gas uint64 = 32000 // Once per CREATE2 operation - SuicideRefundGas uint64 = 24000 // Refunded following a suicide operation. - MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. - TxDataNonZeroGas uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + SstoreSentryGasEIP2200 uint64 = 2300 // Minimum gas required to be present for an SSTORE call, not consumed + SstoreNoopGasEIP2200 uint64 = 800 // Once per SSTORE operation if the value doesn't change. + SstoreDirtyGasEIP2200 uint64 = 800 // Once per SSTORE operation if a dirty value is changed. + SstoreInitGasEIP2200 uint64 = 20000 // Once per SSTORE operation from clean zero to non-zero + SstoreInitRefundEIP2200 uint64 = 19200 // Once per SSTORE operation for resetting to the original zero value + SstoreCleanGasEIP2200 uint64 = 5000 // Once per SSTORE operation from clean non-zero to something else + SstoreCleanRefundEIP2200 uint64 = 4200 // Once per SSTORE operation for resetting to the original non-zero value + SstoreClearRefundEIP2200 uint64 = 15000 // Once per SSTORE operation for clearing an originally existing storage slot + + JumpdestGas uint64 = 1 // Once per JUMPDEST operation. + EpochDuration uint64 = 30000 // Duration between proof-of-work epochs. + + CreateDataGas uint64 = 200 // + CallCreateDepth uint64 = 1024 // Maximum depth of call/create stack. + ExpGas uint64 = 10 // Once per EXP instruction + LogGas uint64 = 375 // Per LOG* operation. + CopyGas uint64 = 3 // + StackLimit uint64 = 1024 // Maximum size of VM stack allowed. + TierStepGas uint64 = 0 // Once per operation, for a selection of them. + LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. + CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction. + Create2Gas uint64 = 32000 // Once per CREATE2 operation + SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation. + MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul) + + // These have been changed during the course of the chain + CallGasFrontier uint64 = 40 // Once per CALL operation & message call transaction. + CallGasEIP150 uint64 = 700 // Static portion of gas for CALL-derivates after EIP 150 (Tangerine) + BalanceGasFrontier uint64 = 20 // The cost of a BALANCE operation + BalanceGasEIP150 uint64 = 400 // The cost of a BALANCE operation after Tangerine + BalanceGasEIP1884 uint64 = 700 // The cost of a BALANCE operation after EIP 1884 (part of Istanbul) + ExtcodeSizeGasFrontier uint64 = 20 // Cost of EXTCODESIZE before EIP 150 (Tangerine) + ExtcodeSizeGasEIP150 uint64 = 700 // Cost of EXTCODESIZE after EIP 150 (Tangerine) + SloadGasFrontier uint64 = 50 + SloadGasEIP150 uint64 = 200 + SloadGasEIP1884 uint64 = 800 // Cost of SLOAD after EIP 1884 (part of Istanbul) + ExtcodeHashGasConstantinople uint64 = 400 // Cost of EXTCODEHASH (introduced in Constantinople) + ExtcodeHashGasEIP1884 uint64 = 700 // Cost of EXTCODEHASH after EIP 1884 (part in Istanbul) + SelfdestructGasEIP150 uint64 = 5000 // Cost of SELFDESTRUCT post EIP 150 (Tangerine) + + // EXP has a dynamic portion depending on the size of the exponent + ExpByteFrontier uint64 = 10 // was set to 10 in Frontier + ExpByteEIP158 uint64 = 50 // was raised to 50 during Eip158 (Spurious Dragon) + + // Extcodecopy has a dynamic AND a static cost. This represents only the + // static portion of the gas. It was changed during EIP 150 (Tangerine) + ExtcodeCopyBaseFrontier uint64 = 20 + ExtcodeCopyBaseEIP150 uint64 = 700 + + // CreateBySelfdestructGas is used when the refunded account is one that does + // not exist. This logic is similar to call. + // Introduced in Tangerine Whistle (Eip 150) + CreateBySelfdestructGas uint64 = 25000 MaxCodeSize = 24576 // Maximum bytecode to permit for a contract // Precompiled contract gas prices - EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price - Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation - Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation - Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation - Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation - IdentityBaseGas uint64 = 15 // Base price for a data copy operation - IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation - ModExpQuadCoeffDiv uint64 = 20 // Divisor for the quadratic particle of the big int modular exponentiation - Bn256AddGas uint64 = 500 // Gas needed for an elliptic curve addition - Bn256ScalarMulGas uint64 = 40000 // Gas needed for an elliptic curve scalar multiplication - Bn256PairingBaseGas uint64 = 100000 // Base price for an elliptic curve pairing check - Bn256PairingPerPointGas uint64 = 80000 // Per-point price for an elliptic curve pairing check + EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price + Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation + Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation + Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation + Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation + IdentityBaseGas uint64 = 15 // Base price for a data copy operation + IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation + ModExpQuadCoeffDiv uint64 = 20 // Divisor for the quadratic particle of the big int modular exponentiation + + Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition + Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition + Bn256ScalarMulGasByzantium uint64 = 40000 // Byzantium gas needed for an elliptic curve scalar multiplication + Bn256ScalarMulGasIstanbul uint64 = 6000 // Gas needed for an elliptic curve scalar multiplication + Bn256PairingBaseGasByzantium uint64 = 100000 // Byzantium base price for an elliptic curve pairing check + Bn256PairingBaseGasIstanbul uint64 = 45000 // Base price for an elliptic curve pairing check + Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check + Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check ) var ( diff --git a/vendor/github.com/ethereum/go-ethereum/params/version.go b/vendor/github.com/ethereum/go-ethereum/params/version.go index 3535c5401..9b6fb3f58 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/version.go +++ b/vendor/github.com/ethereum/go-ethereum/params/version.go @@ -22,8 +22,8 @@ import ( const ( VersionMajor = 1 // Major version component of the current release - VersionMinor = 8 // Minor version component of the current release - VersionPatch = 27 // Patch version component of the current release + VersionMinor = 9 // Minor version component of the current release + VersionPatch = 5 // Patch version component of the current release VersionMeta = "stable" // Version metadata to append to the version string ) @@ -55,10 +55,13 @@ func ArchiveVersion(gitCommit string) string { return vsn } -func VersionWithCommit(gitCommit string) string { +func VersionWithCommit(gitCommit, gitDate string) string { vsn := VersionWithMeta if len(gitCommit) >= 8 { vsn += "-" + gitCommit[:8] } + if (VersionMeta != "stable") && (gitDate != "") { + vsn += "-" + gitDate + } return vsn } diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go index dbbe59959..524395915 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go @@ -26,6 +26,7 @@ import ( "math/big" "reflect" "strings" + "sync" ) var ( @@ -48,95 +49,49 @@ var ( errUintOverflow = errors.New("rlp: uint overflow") errNoPointer = errors.New("rlp: interface given to Decode must be a pointer") errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil") + + streamPool = sync.Pool{ + New: func() interface{} { return new(Stream) }, + } ) -// Decoder is implemented by types that require custom RLP -// decoding rules or need to decode into private fields. +// Decoder is implemented by types that require custom RLP decoding rules or need to decode +// into private fields. // -// The DecodeRLP method should read one value from the given -// Stream. It is not forbidden to read less or more, but it might -// be confusing. +// The DecodeRLP method should read one value from the given Stream. It is not forbidden to +// read less or more, but it might be confusing. type Decoder interface { DecodeRLP(*Stream) error } -// Decode parses RLP-encoded data from r and stores the result in the -// value pointed to by val. Val must be a non-nil pointer. If r does -// not implement ByteReader, Decode will do its own buffering. +// Decode parses RLP-encoded data from r and stores the result in the value pointed to by +// val. Please see package-level documentation for the decoding rules. Val must be a +// non-nil pointer. // -// Decode uses the following type-dependent decoding rules: +// If r does not implement ByteReader, Decode will do its own buffering. // -// If the type implements the Decoder interface, decode calls -// DecodeRLP. -// -// To decode into a pointer, Decode will decode into the value pointed -// to. If the pointer is nil, a new value of the pointer's element -// type is allocated. If the pointer is non-nil, the existing value -// will be reused. -// -// To decode into a struct, Decode expects the input to be an RLP -// list. The decoded elements of the list are assigned to each public -// field in the order given by the struct's definition. The input list -// must contain an element for each decoded field. Decode returns an -// error if there are too few or too many elements. -// -// The decoding of struct fields honours certain struct tags, "tail", -// "nil" and "-". -// -// The "-" tag ignores fields. -// -// For an explanation of "tail", see the example. -// -// The "nil" tag applies to pointer-typed fields and changes the decoding -// rules for the field such that input values of size zero decode as a nil -// pointer. This tag can be useful when decoding recursive types. -// -// type StructWithEmptyOK struct { -// Foo *[20]byte `rlp:"nil"` -// } -// -// To decode into a slice, the input must be a list and the resulting -// slice will contain the input elements in order. For byte slices, -// the input must be an RLP string. Array types decode similarly, with -// the additional restriction that the number of input elements (or -// bytes) must match the array's length. -// -// To decode into a Go string, the input must be an RLP string. The -// input bytes are taken as-is and will not necessarily be valid UTF-8. -// -// To decode into an unsigned integer type, the input must also be an RLP -// string. The bytes are interpreted as a big endian representation of -// the integer. If the RLP string is larger than the bit size of the -// type, Decode will return an error. Decode also supports *big.Int. -// There is no size limit for big integers. -// -// To decode into an interface value, Decode stores one of these -// in the value: -// -// []interface{}, for RLP lists -// []byte, for RLP strings -// -// Non-empty interface types are not supported, nor are booleans, -// signed integers, floating point numbers, maps, channels and -// functions. -// -// Note that Decode does not set an input limit for all readers -// and may be vulnerable to panics cause by huge value sizes. If -// you need an input limit, use +// Note that Decode does not set an input limit for all readers and may be vulnerable to +// panics cause by huge value sizes. If you need an input limit, use // // NewStream(r, limit).Decode(val) func Decode(r io.Reader, val interface{}) error { - // TODO: this could use a Stream from a pool. - return NewStream(r, 0).Decode(val) + stream := streamPool.Get().(*Stream) + defer streamPool.Put(stream) + + stream.Reset(r, 0) + return stream.Decode(val) } -// DecodeBytes parses RLP data from b into val. -// Please see the documentation of Decode for the decoding rules. -// The input must contain exactly one value and no trailing data. +// DecodeBytes parses RLP data from b into val. Please see package-level documentation for +// the decoding rules. The input must contain exactly one value and no trailing data. func DecodeBytes(b []byte, val interface{}) error { - // TODO: this could use a Stream from a pool. r := bytes.NewReader(b) - if err := NewStream(r, uint64(len(b))).Decode(val); err != nil { + + stream := streamPool.Get().(*Stream) + defer streamPool.Put(stream) + + stream.Reset(r, uint64(len(b))) + if err := stream.Decode(val); err != nil { return err } if r.Len() > 0 { @@ -197,14 +152,15 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { switch { case typ == rawValueType: return decodeRawValue, nil - case typ.Implements(decoderInterface): return decodeDecoder, nil - case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface): - return decodeDecoderNoPtr, nil case typ.AssignableTo(reflect.PtrTo(bigInt)): return decodeBigInt, nil case typ.AssignableTo(bigInt): return decodeBigIntNoPtr, nil + case kind == reflect.Ptr: + return makePtrDecoder(typ, tags) + case reflect.PtrTo(typ).Implements(decoderInterface): + return decodeDecoder, nil case isUint(kind): return decodeUint, nil case kind == reflect.Bool: @@ -215,11 +171,6 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { return makeListDecoder(typ, tags) case kind == reflect.Struct: return makeStructDecoder(typ) - case kind == reflect.Ptr: - if tags.nilOK { - return makeOptionalPtrDecoder(typ) - } - return makePtrDecoder(typ) case kind == reflect.Interface: return decodeInterface, nil default: @@ -294,9 +245,9 @@ func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) { } return decodeByteSlice, nil } - etypeinfo, err := cachedTypeInfo1(etype, tags{}) - if err != nil { - return nil, err + etypeinfo := cachedTypeInfo1(etype, tags{}) + if etypeinfo.decoderErr != nil { + return nil, etypeinfo.decoderErr } var dec decoder switch { @@ -434,6 +385,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { if err != nil { return nil, err } + for _, f := range fields { + if f.info.decoderErr != nil { + return nil, structFieldError{typ, f.index, f.info.decoderErr} + } + } dec := func(s *Stream, val reflect.Value) (err error) { if _, err := s.List(); err != nil { return wrapStreamError(err, typ) @@ -451,15 +407,22 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { return dec, nil } -// makePtrDecoder creates a decoder that decodes into -// the pointer's element type. -func makePtrDecoder(typ reflect.Type) (decoder, error) { +// makePtrDecoder creates a decoder that decodes into the pointer's element type. +func makePtrDecoder(typ reflect.Type, tag tags) (decoder, error) { etype := typ.Elem() - etypeinfo, err := cachedTypeInfo1(etype, tags{}) - if err != nil { - return nil, err + etypeinfo := cachedTypeInfo1(etype, tags{}) + switch { + case etypeinfo.decoderErr != nil: + return nil, etypeinfo.decoderErr + case !tag.nilOK: + return makeSimplePtrDecoder(etype, etypeinfo), nil + default: + return makeNilPtrDecoder(etype, etypeinfo, tag.nilKind), nil } - dec := func(s *Stream, val reflect.Value) (err error) { +} + +func makeSimplePtrDecoder(etype reflect.Type, etypeinfo *typeinfo) decoder { + return func(s *Stream, val reflect.Value) (err error) { newval := val if val.IsNil() { newval = reflect.New(etype) @@ -469,30 +432,35 @@ func makePtrDecoder(typ reflect.Type) (decoder, error) { } return err } - return dec, nil } -// makeOptionalPtrDecoder creates a decoder that decodes empty values -// as nil. Non-empty values are decoded into a value of the element type, -// just like makePtrDecoder does. +// makeNilPtrDecoder creates a decoder that decodes empty values as nil. Non-empty +// values are decoded into a value of the element type, just like makePtrDecoder does. // // This decoder is used for pointer-typed struct fields with struct tag "nil". -func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { - etype := typ.Elem() - etypeinfo, err := cachedTypeInfo1(etype, tags{}) - if err != nil { - return nil, err - } - dec := func(s *Stream, val reflect.Value) (err error) { +func makeNilPtrDecoder(etype reflect.Type, etypeinfo *typeinfo, nilKind Kind) decoder { + typ := reflect.PtrTo(etype) + nilPtr := reflect.Zero(typ) + return func(s *Stream, val reflect.Value) (err error) { kind, size, err := s.Kind() - if err != nil || size == 0 && kind != Byte { + if err != nil { + val.Set(nilPtr) + return wrapStreamError(err, typ) + } + // Handle empty values as a nil pointer. + if kind != Byte && size == 0 { + if kind != nilKind { + return &decodeError{ + msg: fmt.Sprintf("wrong kind of empty value (got %v, want %v)", kind, nilKind), + typ: typ, + } + } // rearm s.Kind. This is important because the input // position must advance to the next value even though // we don't read anything. s.kind = -1 - // set the pointer to nil. - val.Set(reflect.Zero(typ)) - return err + val.Set(nilPtr) + return nil } newval := val if val.IsNil() { @@ -503,7 +471,6 @@ func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { } return err } - return dec, nil } var ifsliceType = reflect.TypeOf([]interface{}{}) @@ -532,21 +499,8 @@ func decodeInterface(s *Stream, val reflect.Value) error { return nil } -// This decoder is used for non-pointer values of types -// that implement the Decoder interface using a pointer receiver. -func decodeDecoderNoPtr(s *Stream, val reflect.Value) error { - return val.Addr().Interface().(Decoder).DecodeRLP(s) -} - func decodeDecoder(s *Stream, val reflect.Value) error { - // Decoder instances are not handled using the pointer rule if the type - // implements Decoder with pointer receiver (i.e. always) - // because it might handle empty values specially. - // We need to allocate one here in this case, like makePtrDecoder does. - if val.Kind() == reflect.Ptr && val.IsNil() { - val.Set(reflect.New(val.Type().Elem())) - } - return val.Interface().(Decoder).DecodeRLP(s) + return val.Addr().Interface().(Decoder).DecodeRLP(s) } // Kind represents the kind of value contained in an RLP stream. @@ -802,12 +756,12 @@ func (s *Stream) Decode(val interface{}) error { if rval.IsNil() { return errDecodeIntoNil } - info, err := cachedTypeInfo(rtyp.Elem(), tags{}) + decoder, err := cachedDecoder(rtyp.Elem()) if err != nil { return err } - err = info.decoder(s, rval.Elem()) + err = decoder(s, rval.Elem()) if decErr, ok := err.(*decodeError); ok && len(decErr.ctx) > 0 { // add decode target type to error so context has more meaning decErr.ctx = append(decErr.ctx, fmt.Sprint("(", rtyp.Elem(), ")")) @@ -853,6 +807,7 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) { if s.uintbuf == nil { s.uintbuf = make([]byte, 8) } + s.byteval = 0 } // Kind returns the kind and size of the next value in the diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/doc.go b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go index b3a81fe23..7e6ee8520 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/doc.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go @@ -17,17 +17,114 @@ /* Package rlp implements the RLP serialization format. -The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily -nested arrays of binary data, and RLP is the main encoding method used -to serialize objects in Ethereum. The only purpose of RLP is to encode -structure; encoding specific atomic data types (eg. strings, ints, -floats) is left up to higher-order protocols; in Ethereum integers -must be represented in big endian binary form with no leading zeroes -(thus making the integer value zero equivalent to the empty byte -array). +The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily nested arrays of +binary data, and RLP is the main encoding method used to serialize objects in Ethereum. +The only purpose of RLP is to encode structure; encoding specific atomic data types (eg. +strings, ints, floats) is left up to higher-order protocols. In Ethereum integers must be +represented in big endian binary form with no leading zeroes (thus making the integer +value zero equivalent to the empty string). -RLP values are distinguished by a type tag. The type tag precedes the -value in the input stream and defines the size and kind of the bytes -that follow. +RLP values are distinguished by a type tag. The type tag precedes the value in the input +stream and defines the size and kind of the bytes that follow. + + +Encoding Rules + +Package rlp uses reflection and encodes RLP based on the Go type of the value. + +If the type implements the Encoder interface, Encode calls EncodeRLP. It does not +call EncodeRLP on nil pointer values. + +To encode a pointer, the value being pointed to is encoded. A nil pointer to a struct +type, slice or array always encodes as an empty RLP list unless the slice or array has +elememt type byte. A nil pointer to any other value encodes as the empty string. + +Struct values are encoded as an RLP list of all their encoded public fields. Recursive +struct types are supported. + +To encode slices and arrays, the elements are encoded as an RLP list of the value's +elements. Note that arrays and slices with element type uint8 or byte are always encoded +as an RLP string. + +A Go string is encoded as an RLP string. + +An unsigned integer value is encoded as an RLP string. Zero always encodes as an empty RLP +string. big.Int values are treated as integers. Signed integers (int, int8, int16, ...) +are not supported and will return an error when encoding. + +Boolean values are encoded as the unsigned integers zero (false) and one (true). + +An interface value encodes as the value contained in the interface. + +Floating point numbers, maps, channels and functions are not supported. + + +Decoding Rules + +Decoding uses the following type-dependent rules: + +If the type implements the Decoder interface, DecodeRLP is called. + +To decode into a pointer, the value will be decoded as the element type of the pointer. If +the pointer is nil, a new value of the pointer's element type is allocated. If the pointer +is non-nil, the existing value will be reused. Note that package rlp never leaves a +pointer-type struct field as nil unless one of the "nil" struct tags is present. + +To decode into a struct, decoding expects the input to be an RLP list. The decoded +elements of the list are assigned to each public field in the order given by the struct's +definition. The input list must contain an element for each decoded field. Decoding +returns an error if there are too few or too many elements for the struct. + +To decode into a slice, the input must be a list and the resulting slice will contain the +input elements in order. For byte slices, the input must be an RLP string. Array types +decode similarly, with the additional restriction that the number of input elements (or +bytes) must match the array's defined length. + +To decode into a Go string, the input must be an RLP string. The input bytes are taken +as-is and will not necessarily be valid UTF-8. + +To decode into an unsigned integer type, the input must also be an RLP string. The bytes +are interpreted as a big endian representation of the integer. If the RLP string is larger +than the bit size of the type, decoding will return an error. Decode also supports +*big.Int. There is no size limit for big integers. + +To decode into a boolean, the input must contain an unsigned integer of value zero (false) +or one (true). + +To decode into an interface value, one of these types is stored in the value: + + []interface{}, for RLP lists + []byte, for RLP strings + +Non-empty interface types are not supported when decoding. +Signed integers, floating point numbers, maps, channels and functions cannot be decoded into. + + +Struct Tags + +Package rlp honours certain struct tags: "-", "tail", "nil", "nilList" and "nilString". + +The "-" tag ignores fields. + +The "tail" tag, which may only be used on the last exported struct field, allows slurping +up any excess list elements into a slice. See examples for more details. + +The "nil" tag applies to pointer-typed fields and changes the decoding rules for the field +such that input values of size zero decode as a nil pointer. This tag can be useful when +decoding recursive types. + + type StructWithOptionalFoo struct { + Foo *[20]byte `rlp:"nil"` + } + +RLP supports two kinds of empty values: empty lists and empty strings. When using the +"nil" tag, the kind of empty value allowed for a type is chosen automatically. A struct +field whose Go type is a pointer to an unsigned integer, string, boolean or byte +array/slice expects an empty RLP string. Any other pointer field type encodes/decodes as +an empty RLP list. + +The choice of null value can be made explicit with the "nilList" and "nilString" struct +tags. Using these tags encodes/decodes a Go nil pointer value as the kind of empty +RLP value defined by the tag. */ package rlp diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go index 445b4b5b2..9c9e8d706 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go @@ -49,34 +49,7 @@ type Encoder interface { // perform many small writes in some cases. Consider making w // buffered. // -// Encode uses the following type-dependent encoding rules: -// -// If the type implements the Encoder interface, Encode calls -// EncodeRLP. This is true even for nil pointers, please see the -// documentation for Encoder. -// -// To encode a pointer, the value being pointed to is encoded. For nil -// pointers, Encode will encode the zero value of the type. A nil -// pointer to a struct type always encodes as an empty RLP list. -// A nil pointer to an array encodes as an empty list (or empty string -// if the array has element type byte). -// -// Struct values are encoded as an RLP list of all their encoded -// public fields. Recursive struct types are supported. -// -// To encode slices and arrays, the elements are encoded as an RLP -// list of the value's elements. Note that arrays and slices with -// element type uint8 or byte are always encoded as an RLP string. -// -// A Go string is encoded as an RLP string. -// -// An unsigned integer value is encoded as an RLP string. Zero always -// encodes as an empty RLP string. Encode also supports *big.Int. -// -// An interface value encodes as the value contained in the interface. -// -// Boolean values are not supported, nor are signed integers, floating -// point numbers, maps, channels and functions. +// Please see package-level documentation of encoding rules. func Encode(w io.Writer, val interface{}) error { if outer, ok := w.(*encbuf); ok { // Encode was called by some type's EncodeRLP. @@ -93,7 +66,7 @@ func Encode(w io.Writer, val interface{}) error { } // EncodeToBytes returns the RLP encoding of val. -// Please see the documentation of Encode for the encoding rules. +// Please see package-level documentation for the encoding rules. func EncodeToBytes(val interface{}) ([]byte, error) { eb := encbufPool.Get().(*encbuf) defer encbufPool.Put(eb) @@ -180,11 +153,11 @@ func (w *encbuf) Write(b []byte) (int, error) { func (w *encbuf) encode(val interface{}) error { rval := reflect.ValueOf(val) - ti, err := cachedTypeInfo(rval.Type(), tags{}) + writer, err := cachedWriter(rval.Type()) if err != nil { return err } - return ti.writer(rval, w) + return writer(rval, w) } func (w *encbuf) encodeStringHeader(size int) { @@ -347,16 +320,14 @@ func makeWriter(typ reflect.Type, ts tags) (writer, error) { switch { case typ == rawValueType: return writeRawValue, nil - case typ.Implements(encoderInterface): - return writeEncoder, nil - case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface): - return writeEncoderNoPtr, nil - case kind == reflect.Interface: - return writeInterface, nil case typ.AssignableTo(reflect.PtrTo(bigInt)): return writeBigIntPtr, nil case typ.AssignableTo(bigInt): return writeBigIntNoPtr, nil + case kind == reflect.Ptr: + return makePtrWriter(typ, ts) + case reflect.PtrTo(typ).Implements(encoderInterface): + return makeEncoderWriter(typ), nil case isUint(kind): return writeUint, nil case kind == reflect.Bool: @@ -371,8 +342,8 @@ func makeWriter(typ reflect.Type, ts tags) (writer, error) { return makeSliceWriter(typ, ts) case kind == reflect.Struct: return makeStructWriter(typ) - case kind == reflect.Ptr: - return makePtrWriter(typ) + case kind == reflect.Interface: + return writeInterface, nil default: return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) } @@ -468,26 +439,6 @@ func writeString(val reflect.Value, w *encbuf) error { return nil } -func writeEncoder(val reflect.Value, w *encbuf) error { - return val.Interface().(Encoder).EncodeRLP(w) -} - -// writeEncoderNoPtr handles non-pointer values that implement Encoder -// with a pointer receiver. -func writeEncoderNoPtr(val reflect.Value, w *encbuf) error { - if !val.CanAddr() { - // We can't get the address. It would be possible to make the - // value addressable by creating a shallow copy, but this - // creates other problems so we're not doing it (yet). - // - // package json simply doesn't call MarshalJSON for cases like - // this, but encodes the value as if it didn't implement the - // interface. We don't want to handle it that way. - return fmt.Errorf("rlp: game over: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) - } - return val.Addr().Interface().(Encoder).EncodeRLP(w) -} - func writeInterface(val reflect.Value, w *encbuf) error { if val.IsNil() { // Write empty list. This is consistent with the previous RLP @@ -497,17 +448,17 @@ func writeInterface(val reflect.Value, w *encbuf) error { return nil } eval := val.Elem() - ti, err := cachedTypeInfo(eval.Type(), tags{}) + writer, err := cachedWriter(eval.Type()) if err != nil { return err } - return ti.writer(eval, w) + return writer(eval, w) } func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) { - etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) - if err != nil { - return nil, err + etypeinfo := cachedTypeInfo1(typ.Elem(), tags{}) + if etypeinfo.writerErr != nil { + return nil, etypeinfo.writerErr } writer := func(val reflect.Value, w *encbuf) error { if !ts.tail { @@ -529,6 +480,11 @@ func makeStructWriter(typ reflect.Type) (writer, error) { if err != nil { return nil, err } + for _, f := range fields { + if f.info.writerErr != nil { + return nil, structFieldError{typ, f.index, f.info.writerErr} + } + } writer := func(val reflect.Value, w *encbuf) error { lh := w.list() for _, f := range fields { @@ -542,42 +498,49 @@ func makeStructWriter(typ reflect.Type) (writer, error) { return writer, nil } -func makePtrWriter(typ reflect.Type) (writer, error) { - etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) - if err != nil { - return nil, err +func makePtrWriter(typ reflect.Type, ts tags) (writer, error) { + etypeinfo := cachedTypeInfo1(typ.Elem(), tags{}) + if etypeinfo.writerErr != nil { + return nil, etypeinfo.writerErr } - - // determine nil pointer handler - var nilfunc func(*encbuf) error - kind := typ.Elem().Kind() - switch { - case kind == reflect.Array && isByte(typ.Elem().Elem()): - nilfunc = func(w *encbuf) error { - w.str = append(w.str, 0x80) - return nil - } - case kind == reflect.Struct || kind == reflect.Array: - nilfunc = func(w *encbuf) error { - // encoding the zero value of a struct/array could trigger - // infinite recursion, avoid that. - w.listEnd(w.list()) - return nil - } - default: - zero := reflect.Zero(typ.Elem()) - nilfunc = func(w *encbuf) error { - return etypeinfo.writer(zero, w) - } + // Determine how to encode nil pointers. + var nilKind Kind + if ts.nilOK { + nilKind = ts.nilKind // use struct tag if provided + } else { + nilKind = defaultNilKind(typ.Elem()) } writer := func(val reflect.Value, w *encbuf) error { if val.IsNil() { - return nilfunc(w) + if nilKind == String { + w.str = append(w.str, 0x80) + } else { + w.listEnd(w.list()) + } + return nil } return etypeinfo.writer(val.Elem(), w) } - return writer, err + return writer, nil +} + +func makeEncoderWriter(typ reflect.Type) writer { + if typ.Implements(encoderInterface) { + return func(val reflect.Value, w *encbuf) error { + return val.Interface().(Encoder).EncodeRLP(w) + } + } + w := func(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // package json simply doesn't call MarshalJSON for this case, but encodes the + // value as if it didn't implement the interface. We don't want to handle it that + // way. + return fmt.Errorf("rlp: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) + } + return val.Addr().Interface().(Encoder).EncodeRLP(w) + } + return w } // putint writes i to the beginning of b in big endian byte diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go index 8c2dd518e..e9a1e3f9e 100644 --- a/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go +++ b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go @@ -29,26 +29,34 @@ var ( ) type typeinfo struct { - decoder - writer + decoder decoder + decoderErr error // error from makeDecoder + writer writer + writerErr error // error from makeWriter } -// represents struct tags +// tags represents struct tags. type tags struct { // rlp:"nil" controls whether empty input results in a nil pointer. nilOK bool + + // This controls whether nil pointers are encoded/decoded as empty strings + // or empty lists. + nilKind Kind + // rlp:"tail" controls whether this field swallows additional list // elements. It can only be set for the last field, which must be // of slice type. tail bool + // rlp:"-" ignores fields. ignored bool } +// typekey is the key of a type in typeCache. It includes the struct tags because +// they might generate a different decoder. type typekey struct { reflect.Type - // the key must include the struct tags because they - // might generate a different decoder. tags } @@ -56,12 +64,22 @@ type decoder func(*Stream, reflect.Value) error type writer func(reflect.Value, *encbuf) error -func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { +func cachedDecoder(typ reflect.Type) (decoder, error) { + info := cachedTypeInfo(typ, tags{}) + return info.decoder, info.decoderErr +} + +func cachedWriter(typ reflect.Type) (writer, error) { + info := cachedTypeInfo(typ, tags{}) + return info.writer, info.writerErr +} + +func cachedTypeInfo(typ reflect.Type, tags tags) *typeinfo { typeCacheMutex.RLock() info := typeCache[typekey{typ, tags}] typeCacheMutex.RUnlock() if info != nil { - return info, nil + return info } // not in the cache, need to generate info for this type. typeCacheMutex.Lock() @@ -69,25 +87,20 @@ func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { return cachedTypeInfo1(typ, tags) } -func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) { +func cachedTypeInfo1(typ reflect.Type, tags tags) *typeinfo { key := typekey{typ, tags} info := typeCache[key] if info != nil { // another goroutine got the write lock first - return info, nil + return info } // put a dummy value into the cache before generating. // if the generator tries to lookup itself, it will get // the dummy value and won't call itself recursively. - typeCache[key] = new(typeinfo) - info, err := genTypeInfo(typ, tags) - if err != nil { - // remove the dummy value if the generator fails - delete(typeCache, key) - return nil, err - } - *typeCache[key] = *info - return typeCache[key], err + info = new(typeinfo) + typeCache[key] = info + info.generate(typ, tags) + return info } type field struct { @@ -96,26 +109,43 @@ type field struct { } func structFields(typ reflect.Type) (fields []field, err error) { + lastPublic := lastPublicField(typ) for i := 0; i < typ.NumField(); i++ { if f := typ.Field(i); f.PkgPath == "" { // exported - tags, err := parseStructTag(typ, i) + tags, err := parseStructTag(typ, i, lastPublic) if err != nil { return nil, err } if tags.ignored { continue } - info, err := cachedTypeInfo1(f.Type, tags) - if err != nil { - return nil, err - } + info := cachedTypeInfo1(f.Type, tags) fields = append(fields, field{i, info}) } } return fields, nil } -func parseStructTag(typ reflect.Type, fi int) (tags, error) { +type structFieldError struct { + typ reflect.Type + field int + err error +} + +func (e structFieldError) Error() string { + return fmt.Sprintf("%v (struct field %v.%s)", e.err, e.typ, e.typ.Field(e.field).Name) +} + +type structTagError struct { + typ reflect.Type + field, tag, err string +} + +func (e structTagError) Error() string { + return fmt.Sprintf("rlp: invalid struct tag %q for %v.%s (%s)", e.tag, e.typ, e.field, e.err) +} + +func parseStructTag(typ reflect.Type, fi, lastPublic int) (tags, error) { f := typ.Field(fi) var ts tags for _, t := range strings.Split(f.Tag.Get("rlp"), ",") { @@ -123,15 +153,26 @@ func parseStructTag(typ reflect.Type, fi int) (tags, error) { case "": case "-": ts.ignored = true - case "nil": + case "nil", "nilString", "nilList": ts.nilOK = true + if f.Type.Kind() != reflect.Ptr { + return ts, structTagError{typ, f.Name, t, "field is not a pointer"} + } + switch t { + case "nil": + ts.nilKind = defaultNilKind(f.Type.Elem()) + case "nilString": + ts.nilKind = String + case "nilList": + ts.nilKind = List + } case "tail": ts.tail = true - if fi != typ.NumField()-1 { - return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) + if fi != lastPublic { + return ts, structTagError{typ, f.Name, t, "must be on last field"} } if f.Type.Kind() != reflect.Slice { - return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) + return ts, structTagError{typ, f.Name, t, "field type is not slice"} } default: return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) @@ -140,17 +181,35 @@ func parseStructTag(typ reflect.Type, fi int) (tags, error) { return ts, nil } -func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { - info = new(typeinfo) - if info.decoder, err = makeDecoder(typ, tags); err != nil { - return nil, err +func lastPublicField(typ reflect.Type) int { + last := 0 + for i := 0; i < typ.NumField(); i++ { + if typ.Field(i).PkgPath == "" { + last = i + } } - if info.writer, err = makeWriter(typ, tags); err != nil { - return nil, err + return last +} + +func (i *typeinfo) generate(typ reflect.Type, tags tags) { + i.decoder, i.decoderErr = makeDecoder(typ, tags) + i.writer, i.writerErr = makeWriter(typ, tags) +} + +// defaultNilKind determines whether a nil pointer to typ encodes/decodes +// as an empty string or empty list. +func defaultNilKind(typ reflect.Type) Kind { + k := typ.Kind() + if isUint(k) || k == reflect.String || k == reflect.Bool || isByteArray(typ) { + return String } - return info, nil + return List } func isUint(k reflect.Kind) bool { return k >= reflect.Uint && k <= reflect.Uintptr } + +func isByteArray(typ reflect.Type) bool { + return (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Array) && isByte(typ.Elem()) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/client.go b/vendor/github.com/ethereum/go-ethereum/rpc/client.go index 6254c95ff..4b65d0042 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/client.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/client.go @@ -18,17 +18,13 @@ package rpc import ( "bytes" - "container/list" "context" "encoding/json" "errors" "fmt" - "net" "net/url" "reflect" "strconv" - "strings" - "sync" "sync/atomic" "time" @@ -39,14 +35,14 @@ var ( ErrClientQuit = errors.New("client is closed") ErrNoResult = errors.New("no result in JSON-RPC response") ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow") + errClientReconnected = errors.New("client reconnected") + errDead = errors.New("connection lost") ) const ( // Timeouts - tcpKeepAliveInterval = 30 * time.Second - defaultDialTimeout = 10 * time.Second // used when dialing if the context has no deadline - defaultWriteTimeout = 10 * time.Second // used for calls if the context has no deadline - subscribeTimeout = 5 * time.Second // overall timeout eth_subscribe, rpc_modules calls + defaultDialTimeout = 10 * time.Second // used if context has no deadline + subscribeTimeout = 5 * time.Second // overall timeout eth_subscribe, rpc_modules calls ) const ( @@ -76,56 +72,57 @@ type BatchElem struct { Error error } -// A value of this type can a JSON-RPC request, notification, successful response or -// error response. Which one it is depends on the fields. -type jsonrpcMessage struct { - Version string `json:"jsonrpc"` - ID json.RawMessage `json:"id,omitempty"` - Method string `json:"method,omitempty"` - Params json.RawMessage `json:"params,omitempty"` - Error *jsonError `json:"error,omitempty"` - Result json.RawMessage `json:"result,omitempty"` -} - -func (msg *jsonrpcMessage) isNotification() bool { - return msg.ID == nil && msg.Method != "" -} - -func (msg *jsonrpcMessage) isResponse() bool { - return msg.hasValidID() && msg.Method == "" && len(msg.Params) == 0 -} - -func (msg *jsonrpcMessage) hasValidID() bool { - return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '[' -} - -func (msg *jsonrpcMessage) String() string { - b, _ := json.Marshal(msg) - return string(b) -} - // Client represents a connection to an RPC server. type Client struct { - idCounter uint32 - connectFunc func(ctx context.Context) (net.Conn, error) - isHTTP bool + idgen func() ID // for subscriptions + isHTTP bool + services *serviceRegistry - // writeConn is only safe to access outside dispatch, with the - // write lock held. The write lock is taken by sending on - // requestOp and released by sending on sendDone. - writeConn net.Conn + idCounter uint32 + + // This function, if non-nil, is called when the connection is lost. + reconnectFunc reconnectFunc + + // writeConn is used for writing to the connection on the caller's goroutine. It should + // only be accessed outside of dispatch, with the write lock held. The write lock is + // taken by sending on requestOp and released by sending on sendDone. + writeConn jsonWriter // for dispatch close chan struct{} - closing chan struct{} // closed when client is quitting - didClose chan struct{} // closed when client quits - reconnected chan net.Conn // where write/reconnect sends the new connection - readErr chan error // errors from read - readResp chan []*jsonrpcMessage // valid messages from read - requestOp chan *requestOp // for registering response IDs - sendDone chan error // signals write completion, releases write lock - respWait map[string]*requestOp // active requests - subs map[string]*ClientSubscription // active subscriptions + closing chan struct{} // closed when client is quitting + didClose chan struct{} // closed when client quits + reconnected chan ServerCodec // where write/reconnect sends the new connection + readOp chan readOp // read messages + readErr chan error // errors from read + reqInit chan *requestOp // register response IDs, takes write lock + reqSent chan error // signals write completion, releases write lock + reqTimeout chan *requestOp // removes response IDs when call timeout expires +} + +type reconnectFunc func(ctx context.Context) (ServerCodec, error) + +type clientContextKey struct{} + +type clientConn struct { + codec ServerCodec + handler *handler +} + +func (c *Client) newClientConn(conn ServerCodec) *clientConn { + ctx := context.WithValue(context.Background(), clientContextKey{}, c) + handler := newHandler(ctx, conn, c.idgen, c.services) + return &clientConn{conn, handler} +} + +func (cc *clientConn) close(err error, inflightReq *requestOp) { + cc.handler.close(err, inflightReq) + cc.codec.Close() +} + +type readOp struct { + msgs []*jsonrpcMessage + batch bool } type requestOp struct { @@ -135,9 +132,16 @@ type requestOp struct { sub *ClientSubscription // only set for EthSubscribe requests } -func (op *requestOp) wait(ctx context.Context) (*jsonrpcMessage, error) { +func (op *requestOp) wait(ctx context.Context, c *Client) (*jsonrpcMessage, error) { select { case <-ctx.Done(): + // Send the timeout to dispatch so it can remove the request IDs. + if !c.isHTTP { + select { + case c.reqTimeout <- op: + case <-c.closing: + } + } return nil, ctx.Err() case resp := <-op.resp: return resp, op.err @@ -181,36 +185,57 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) { } } -func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) { - conn, err := connectFunc(initctx) +// Client retrieves the client from the context, if any. This can be used to perform +// 'reverse calls' in a handler method. +func ClientFromContext(ctx context.Context) (*Client, bool) { + client, ok := ctx.Value(clientContextKey{}).(*Client) + return client, ok +} + +func newClient(initctx context.Context, connect reconnectFunc) (*Client, error) { + conn, err := connect(initctx) if err != nil { return nil, err } + c := initClient(conn, randomIDGenerator(), new(serviceRegistry)) + c.reconnectFunc = connect + return c, nil +} + +func initClient(conn ServerCodec, idgen func() ID, services *serviceRegistry) *Client { _, isHTTP := conn.(*httpConn) c := &Client{ - writeConn: conn, + idgen: idgen, isHTTP: isHTTP, - connectFunc: connectFunc, + services: services, + writeConn: conn, close: make(chan struct{}), closing: make(chan struct{}), didClose: make(chan struct{}), - reconnected: make(chan net.Conn), + reconnected: make(chan ServerCodec), + readOp: make(chan readOp), readErr: make(chan error), - readResp: make(chan []*jsonrpcMessage), - requestOp: make(chan *requestOp), - sendDone: make(chan error, 1), - respWait: make(map[string]*requestOp), - subs: make(map[string]*ClientSubscription), + reqInit: make(chan *requestOp), + reqSent: make(chan error, 1), + reqTimeout: make(chan *requestOp), } if !isHTTP { go c.dispatch(conn) } - return c, nil + return c +} + +// RegisterName creates a service for the given receiver type under the given name. When no +// methods on the given receiver match the criteria to be either a RPC method or a +// subscription an error is returned. Otherwise a new service is created and added to the +// service collection this client provides to the server. +func (c *Client) RegisterName(name string, receiver interface{}) error { + return c.services.registerName(name, receiver) } func (c *Client) nextID() json.RawMessage { id := atomic.AddUint32(&c.idCounter, 1) - return []byte(strconv.FormatUint(uint64(id), 10)) + return strconv.AppendUint(nil, uint64(id), 10) } // SupportedModules calls the rpc_modules method, retrieving the list of @@ -267,7 +292,7 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str } // dispatch has accepted the request and will close the channel when it quits. - switch resp, err := op.wait(ctx); { + switch resp, err := op.wait(ctx, c); { case err != nil: return err case resp.Error != nil: @@ -325,7 +350,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error { // Wait for all responses to come back. for n := 0; n < len(b) && err == nil; n++ { var resp *jsonrpcMessage - resp, err = op.wait(ctx) + resp, err = op.wait(ctx, c) if err != nil { break } @@ -352,6 +377,22 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error { return err } +// Notify sends a notification, i.e. a method call that doesn't expect a response. +func (c *Client) Notify(ctx context.Context, method string, args ...interface{}) error { + op := new(requestOp) + msg, err := c.newMessage(method, args...) + if err != nil { + return err + } + msg.ID = nil + + if c.isHTTP { + return c.sendHTTP(ctx, op, msg) + } else { + return c.send(ctx, op, msg) + } +} + // EthSubscribe registers a subscripion under the "eth" namespace. func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) { return c.Subscribe(ctx, "eth", channel, args...) @@ -370,7 +411,7 @@ func (c *Client) ShhSubscribe(ctx context.Context, channel interface{}, args ... // The context argument cancels the RPC request that sets up the subscription but has no // effect on the subscription after Subscribe has returned. // -// Slow subscribers will be dropped eventually. Client buffers up to 8000 notifications +// Slow subscribers will be dropped eventually. Client buffers up to 20000 notifications // before considering the subscriber dead. The subscription Err channel will receive // ErrSubscriptionQueueOverflow. Use a sufficiently large buffer on the channel or ensure // that the channel usually has at least one reader to prevent this issue. @@ -402,30 +443,30 @@ func (c *Client) Subscribe(ctx context.Context, namespace string, channel interf if err := c.send(ctx, op, msg); err != nil { return nil, err } - if _, err := op.wait(ctx); err != nil { + if _, err := op.wait(ctx, c); err != nil { return nil, err } return op.sub, nil } func (c *Client) newMessage(method string, paramsIn ...interface{}) (*jsonrpcMessage, error) { - params, err := json.Marshal(paramsIn) - if err != nil { - return nil, err + msg := &jsonrpcMessage{Version: vsn, ID: c.nextID(), Method: method} + if paramsIn != nil { // prevent sending "params":null + var err error + if msg.Params, err = json.Marshal(paramsIn); err != nil { + return nil, err + } } - return &jsonrpcMessage{Version: "2.0", ID: c.nextID(), Method: method, Params: params}, nil + return msg, nil } // send registers op with the dispatch loop, then sends msg on the connection. // if sending fails, op is deregistered. func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error { select { - case c.requestOp <- op: - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("sending ", msg) - }}) + case c.reqInit <- op: err := c.write(ctx, msg) - c.sendDone <- err + c.reqSent <- err return err case <-ctx.Done(): // This can happen if the client is overloaded or unable to keep up with @@ -433,25 +474,17 @@ func (c *Client) send(ctx context.Context, op *requestOp, msg interface{}) error return ctx.Err() case <-c.closing: return ErrClientQuit - case <-c.didClose: - return ErrClientQuit } } func (c *Client) write(ctx context.Context, msg interface{}) error { - deadline, ok := ctx.Deadline() - if !ok { - deadline = time.Now().Add(defaultWriteTimeout) - } // The previous write failed. Try to establish a new connection. if c.writeConn == nil { if err := c.reconnect(ctx); err != nil { return err } } - c.writeConn.SetWriteDeadline(deadline) - err := json.NewEncoder(c.writeConn).Encode(msg) - c.writeConn.SetWriteDeadline(time.Time{}) + err := c.writeConn.Write(ctx, msg) if err != nil { c.writeConn = nil } @@ -459,9 +492,18 @@ func (c *Client) write(ctx context.Context, msg interface{}) error { } func (c *Client) reconnect(ctx context.Context) error { - newconn, err := c.connectFunc(ctx) + if c.reconnectFunc == nil { + return errDead + } + + if _, ok := ctx.Deadline(); !ok { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, defaultDialTimeout) + defer cancel() + } + newconn, err := c.reconnectFunc(ctx) if err != nil { - log.Trace(fmt.Sprintf("reconnect failed: %v", err)) + log.Trace("RPC client reconnect failed", "err", err) return err } select { @@ -477,322 +519,107 @@ func (c *Client) reconnect(ctx context.Context) error { // dispatch is the main loop of the client. // It sends read messages to waiting calls to Call and BatchCall // and subscription notifications to registered subscriptions. -func (c *Client) dispatch(conn net.Conn) { - // Spawn the initial read loop. - go c.read(conn) - +func (c *Client) dispatch(codec ServerCodec) { var ( - lastOp *requestOp // tracks last send operation - requestOpLock = c.requestOp // nil while the send lock is held - reading = true // if true, a read loop is running + lastOp *requestOp // tracks last send operation + reqInitLock = c.reqInit // nil while the send lock is held + conn = c.newClientConn(codec) + reading = true ) - defer close(c.didClose) defer func() { close(c.closing) - c.closeRequestOps(ErrClientQuit) - conn.Close() if reading { - // Empty read channels until read is dead. - for { - select { - case <-c.readResp: - case <-c.readErr: - return - } - } + conn.close(ErrClientQuit, nil) + c.drainRead() } + close(c.didClose) }() + // Spawn the initial read loop. + go c.read(codec) + for { select { case <-c.close: return - // Read path. - case batch := <-c.readResp: - for _, msg := range batch { - switch { - case msg.isNotification(): - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: notification ", msg) - }}) - c.handleNotification(msg) - case msg.isResponse(): - log.Trace("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: response ", msg) - }}) - c.handleResponse(msg) - default: - log.Debug("", "msg", log.Lazy{Fn: func() string { - return fmt.Sprint("<-readResp: dropping weird message", msg) - }}) - // TODO: maybe close - } + // Read path: + case op := <-c.readOp: + if op.batch { + conn.handler.handleBatch(op.msgs) + } else { + conn.handler.handleMsg(op.msgs[0]) } case err := <-c.readErr: - log.Debug("<-readErr", "err", err) - c.closeRequestOps(err) - conn.Close() + conn.handler.log.Debug("RPC connection read error", "err", err) + conn.close(err, lastOp) reading = false - case newconn := <-c.reconnected: - log.Debug("<-reconnected", "reading", reading, "remote", conn.RemoteAddr()) + // Reconnect: + case newcodec := <-c.reconnected: + log.Debug("RPC client reconnected", "reading", reading, "conn", newcodec.RemoteAddr()) if reading { - // Wait for the previous read loop to exit. This is a rare case. - conn.Close() - <-c.readErr + // Wait for the previous read loop to exit. This is a rare case which + // happens if this loop isn't notified in time after the connection breaks. + // In those cases the caller will notice first and reconnect. Closing the + // handler terminates all waiting requests (closing op.resp) except for + // lastOp, which will be transferred to the new handler. + conn.close(errClientReconnected, lastOp) + c.drainRead() } - go c.read(newconn) + go c.read(newcodec) reading = true - conn = newconn + conn = c.newClientConn(newcodec) + // Re-register the in-flight request on the new handler + // because that's where it will be sent. + conn.handler.addRequestOp(lastOp) - // Send path. - case op := <-requestOpLock: - // Stop listening for further send ops until the current one is done. - requestOpLock = nil + // Send path: + case op := <-reqInitLock: + // Stop listening for further requests until the current one has been sent. + reqInitLock = nil lastOp = op - for _, id := range op.ids { - c.respWait[string(id)] = op - } + conn.handler.addRequestOp(op) - case err := <-c.sendDone: + case err := <-c.reqSent: if err != nil { - // Remove response handlers for the last send. We remove those here - // because the error is already handled in Call or BatchCall. When the - // read loop goes down, it will signal all other current operations. - for _, id := range lastOp.ids { - delete(c.respWait, string(id)) - } + // Remove response handlers for the last send. When the read loop + // goes down, it will signal all other current operations. + conn.handler.removeRequestOp(lastOp) } - // Listen for send ops again. - requestOpLock = c.requestOp + // Let the next request in. + reqInitLock = c.reqInit lastOp = nil + + case op := <-c.reqTimeout: + conn.handler.removeRequestOp(op) } } } -// closeRequestOps unblocks pending send ops and active subscriptions. -func (c *Client) closeRequestOps(err error) { - didClose := make(map[*requestOp]bool) - - for id, op := range c.respWait { - // Remove the op so that later calls will not close op.resp again. - delete(c.respWait, id) - - if !didClose[op] { - op.err = err - close(op.resp) - didClose[op] = true - } - } - for id, sub := range c.subs { - delete(c.subs, id) - sub.quitWithError(err, false) - } -} - -func (c *Client) handleNotification(msg *jsonrpcMessage) { - if !strings.HasSuffix(msg.Method, notificationMethodSuffix) { - log.Debug("dropping non-subscription message", "msg", msg) - return - } - var subResult struct { - ID string `json:"subscription"` - Result json.RawMessage `json:"result"` - } - if err := json.Unmarshal(msg.Params, &subResult); err != nil { - log.Debug("dropping invalid subscription message", "msg", msg) - return - } - if c.subs[subResult.ID] != nil { - c.subs[subResult.ID].deliver(subResult.Result) - } -} - -func (c *Client) handleResponse(msg *jsonrpcMessage) { - op := c.respWait[string(msg.ID)] - if op == nil { - log.Debug("unsolicited response", "msg", msg) - return - } - delete(c.respWait, string(msg.ID)) - // For normal responses, just forward the reply to Call/BatchCall. - if op.sub == nil { - op.resp <- msg - return - } - // For subscription responses, start the subscription if the server - // indicates success. EthSubscribe gets unblocked in either case through - // the op.resp channel. - defer close(op.resp) - if msg.Error != nil { - op.err = msg.Error - return - } - if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil { - go op.sub.start() - c.subs[op.sub.subid] = op.sub - } -} - -// Reading happens on a dedicated goroutine. - -func (c *Client) read(conn net.Conn) error { - var ( - buf json.RawMessage - dec = json.NewDecoder(conn) - ) - readMessage := func() (rs []*jsonrpcMessage, err error) { - buf = buf[:0] - if err = dec.Decode(&buf); err != nil { - return nil, err - } - if isBatch(buf) { - err = json.Unmarshal(buf, &rs) - } else { - rs = make([]*jsonrpcMessage, 1) - err = json.Unmarshal(buf, &rs[0]) - } - return rs, err - } - +// drainRead drops read messages until an error occurs. +func (c *Client) drainRead() { for { - resp, err := readMessage() + select { + case <-c.readOp: + case <-c.readErr: + return + } + } +} + +// read decodes RPC messages from a codec, feeding them into dispatch. +func (c *Client) read(codec ServerCodec) { + for { + msgs, batch, err := codec.Read() + if _, ok := err.(*json.SyntaxError); ok { + codec.Write(context.Background(), errorMessage(&parseError{err.Error()})) + } if err != nil { c.readErr <- err - return err + return } - c.readResp <- resp + c.readOp <- readOp{msgs, batch} } } - -// Subscriptions. - -// A ClientSubscription represents a subscription established through EthSubscribe. -type ClientSubscription struct { - client *Client - etype reflect.Type - channel reflect.Value - namespace string - subid string - in chan json.RawMessage - - quitOnce sync.Once // ensures quit is closed once - quit chan struct{} // quit is closed when the subscription exits - errOnce sync.Once // ensures err is closed once - err chan error -} - -func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription { - sub := &ClientSubscription{ - client: c, - namespace: namespace, - etype: channel.Type().Elem(), - channel: channel, - quit: make(chan struct{}), - err: make(chan error, 1), - in: make(chan json.RawMessage), - } - return sub -} - -// Err returns the subscription error channel. The intended use of Err is to schedule -// resubscription when the client connection is closed unexpectedly. -// -// The error channel receives a value when the subscription has ended due -// to an error. The received error is nil if Close has been called -// on the underlying client and no other error has occurred. -// -// The error channel is closed when Unsubscribe is called on the subscription. -func (sub *ClientSubscription) Err() <-chan error { - return sub.err -} - -// Unsubscribe unsubscribes the notification and closes the error channel. -// It can safely be called more than once. -func (sub *ClientSubscription) Unsubscribe() { - sub.quitWithError(nil, true) - sub.errOnce.Do(func() { close(sub.err) }) -} - -func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) { - sub.quitOnce.Do(func() { - // The dispatch loop won't be able to execute the unsubscribe call - // if it is blocked on deliver. Close sub.quit first because it - // unblocks deliver. - close(sub.quit) - if unsubscribeServer { - sub.requestUnsubscribe() - } - if err != nil { - if err == ErrClientQuit { - err = nil // Adhere to subscription semantics. - } - sub.err <- err - } - }) -} - -func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) { - select { - case sub.in <- result: - return true - case <-sub.quit: - return false - } -} - -func (sub *ClientSubscription) start() { - sub.quitWithError(sub.forward()) -} - -func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) { - cases := []reflect.SelectCase{ - {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)}, - {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)}, - {Dir: reflect.SelectSend, Chan: sub.channel}, - } - buffer := list.New() - defer buffer.Init() - for { - var chosen int - var recv reflect.Value - if buffer.Len() == 0 { - // Idle, omit send case. - chosen, recv, _ = reflect.Select(cases[:2]) - } else { - // Non-empty buffer, send the first queued item. - cases[2].Send = reflect.ValueOf(buffer.Front().Value) - chosen, recv, _ = reflect.Select(cases) - } - - switch chosen { - case 0: // <-sub.quit - return nil, false - case 1: // <-sub.in - val, err := sub.unmarshal(recv.Interface().(json.RawMessage)) - if err != nil { - return err, true - } - if buffer.Len() == maxClientSubscriptionBuffer { - return ErrSubscriptionQueueOverflow, true - } - buffer.PushBack(val) - case 2: // sub.channel<- - cases[2].Send = reflect.Value{} // Don't hold onto the value. - buffer.Remove(buffer.Front()) - } - } -} - -func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) { - val := reflect.New(sub.etype) - err := json.Unmarshal(result, val.Interface()) - return val.Elem().Interface(), err -} - -func (sub *ClientSubscription) requestUnsubscribe() error { - var result interface{} - return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid) -} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix.go b/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix.go new file mode 100644 index 000000000..2f98d6499 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix.go @@ -0,0 +1,33 @@ +// Copyright 2019 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 . + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package rpc + +/* +#include + +int max_socket_path_size() { +struct sockaddr_un s; +return sizeof(s.sun_path); +} +*/ +import "C" + +var ( + max_path_size = C.max_socket_path_size() +) diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix_nocgo.go b/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix_nocgo.go new file mode 100644 index 000000000..ecb231f92 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/constants_unix_nocgo.go @@ -0,0 +1,25 @@ +// Copyright 2019 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 . + +// +build !cgo,!windows + +package rpc + +var ( + // On Linux, sun_path is 108 bytes in size + // see http://man7.org/linux/man-pages/man7/unix.7.html + max_path_size = 108 +) diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/doc.go b/vendor/github.com/ethereum/go-ethereum/rpc/doc.go index c60381b5a..e5840c32d 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/doc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/doc.go @@ -15,43 +15,49 @@ // along with the go-ethereum library. If not, see . /* -Package rpc provides access to the exported methods of an object across a network -or other I/O connection. After creating a server instance objects can be registered, -making it visible from the outside. Exported methods that follow specific -conventions can be called remotely. It also has support for the publish/subscribe -pattern. + +Package rpc implements bi-directional JSON-RPC 2.0 on multiple transports. + +It provides access to the exported methods of an object across a network or other I/O +connection. After creating a server or client instance, objects can be registered to make +them visible as 'services'. Exported methods that follow specific conventions can be +called remotely. It also has support for the publish/subscribe pattern. + +RPC Methods Methods that satisfy the following criteria are made available for remote access: - - object must be exported + - method must be exported - method returns 0, 1 (response or error) or 2 (response and error) values - method argument(s) must be exported or builtin types - method returned value(s) must be exported or builtin types An example method: + func (s *CalcService) Add(a, b int) (int, error) -When the returned error isn't nil the returned integer is ignored and the error is -sent back to the client. Otherwise the returned integer is sent back to the client. +When the returned error isn't nil the returned integer is ignored and the error is sent +back to the client. Otherwise the returned integer is sent back to the client. -Optional arguments are supported by accepting pointer values as arguments. E.g. -if we want to do the addition in an optional finite field we can accept a mod -argument as pointer value. +Optional arguments are supported by accepting pointer values as arguments. E.g. if we want +to do the addition in an optional finite field we can accept a mod argument as pointer +value. - func (s *CalService) Add(a, b int, mod *int) (int, error) + func (s *CalcService) Add(a, b int, mod *int) (int, error) -This RPC method can be called with 2 integers and a null value as third argument. -In that case the mod argument will be nil. Or it can be called with 3 integers, -in that case mod will be pointing to the given third argument. Since the optional -argument is the last argument the RPC package will also accept 2 integers as -arguments. It will pass the mod argument as nil to the RPC method. +This RPC method can be called with 2 integers and a null value as third argument. In that +case the mod argument will be nil. Or it can be called with 3 integers, in that case mod +will be pointing to the given third argument. Since the optional argument is the last +argument the RPC package will also accept 2 integers as arguments. It will pass the mod +argument as nil to the RPC method. -The server offers the ServeCodec method which accepts a ServerCodec instance. It will -read requests from the codec, process the request and sends the response back to the -client using the codec. The server can execute requests concurrently. Responses -can be sent back to the client out of order. +The server offers the ServeCodec method which accepts a ServerCodec instance. It will read +requests from the codec, process the request and sends the response back to the client +using the codec. The server can execute requests concurrently. Responses can be sent back +to the client out of order. An example server which uses the JSON codec: + type CalculatorService struct {} func (s *CalculatorService) Add(a, b int) int { @@ -73,26 +79,40 @@ An example server which uses the JSON codec: for { c, _ := l.AcceptUnix() codec := v2.NewJSONCodec(c) - go server.ServeCodec(codec) + go server.ServeCodec(codec, 0) } +Subscriptions + The package also supports the publish subscribe pattern through the use of subscriptions. -A method that is considered eligible for notifications must satisfy the following criteria: - - object must be exported +A method that is considered eligible for notifications must satisfy the following +criteria: + - method must be exported - first method argument type must be context.Context - method argument(s) must be exported or builtin types - - method must return the tuple Subscription, error + - method must have return types (rpc.Subscription, error) An example method: - func (s *BlockChainService) NewBlocks(ctx context.Context) (Subscription, error) { + + func (s *BlockChainService) NewBlocks(ctx context.Context) (rpc.Subscription, error) { ... } -Subscriptions are deleted when: - - the user sends an unsubscribe request - - the connection which was used to create the subscription is closed. This can be initiated - by the client and server. The server will close the connection on a write error or when - the queue of buffered notifications gets too big. +When the service containing the subscription method is registered to the server, for +example under the "blockchain" namespace, a subscription is created by calling the +"blockchain_subscribe" method. + +Subscriptions are deleted when the user sends an unsubscribe request or when the +connection which was used to create the subscription is closed. This can be initiated by +the client and server. The server will close the connection for any write error. + +For more information about subscriptions, see https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB. + +Reverse Calls + +In any method handler, an instance of rpc.Client can be accessed through the +ClientFromContext method. Using this client instance, server-to-client method calls can be +performed on the RPC connection. */ package rpc diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/errors.go b/vendor/github.com/ethereum/go-ethereum/rpc/errors.go index 9cf9dc60c..c3aa826cc 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/errors.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/errors.go @@ -18,18 +18,31 @@ package rpc import "fmt" -// request is for an unknown service -type methodNotFoundError struct { - service string - method string -} +const defaultErrorCode = -32000 + +type methodNotFoundError struct{ method string } func (e *methodNotFoundError) ErrorCode() int { return -32601 } func (e *methodNotFoundError) Error() string { - return fmt.Sprintf("The method %s%s%s does not exist/is not available", e.service, serviceMethodSeparator, e.method) + return fmt.Sprintf("the method %s does not exist/is not available", e.method) } +type subscriptionNotFoundError struct{ namespace, subscription string } + +func (e *subscriptionNotFoundError) ErrorCode() int { return -32601 } + +func (e *subscriptionNotFoundError) Error() string { + return fmt.Sprintf("no %q subscription in %s namespace", e.subscription, e.namespace) +} + +// Invalid JSON was received by the server. +type parseError struct{ message string } + +func (e *parseError) ErrorCode() int { return -32700 } + +func (e *parseError) Error() string { return e.message } + // received message isn't a valid request type invalidRequestError struct{ message string } @@ -50,17 +63,3 @@ type invalidParamsError struct{ message string } func (e *invalidParamsError) ErrorCode() int { return -32602 } func (e *invalidParamsError) Error() string { return e.message } - -// logic error, callback returned an error -type callbackError struct{ message string } - -func (e *callbackError) ErrorCode() int { return -32000 } - -func (e *callbackError) Error() string { return e.message } - -// issued when a request is received after the server is issued to stop. -type shutdownError struct{} - -func (e *shutdownError) ErrorCode() int { return -32000 } - -func (e *shutdownError) Error() string { return "server is shutting down" } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go b/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go new file mode 100644 index 000000000..a14fd09d5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/gzip.go @@ -0,0 +1,66 @@ +// Copyright 2019 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 rpc + +import ( + "compress/gzip" + "io" + "io/ioutil" + "net/http" + "strings" + "sync" +) + +var gzPool = sync.Pool{ + New: func() interface{} { + w := gzip.NewWriter(ioutil.Discard) + return w + }, +} + +type gzipResponseWriter struct { + io.Writer + http.ResponseWriter +} + +func (w *gzipResponseWriter) WriteHeader(status int) { + w.Header().Del("Content-Length") + w.ResponseWriter.WriteHeader(status) +} + +func (w *gzipResponseWriter) Write(b []byte) (int, error) { + return w.Writer.Write(b) +} + +func newGzipHandler(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + next.ServeHTTP(w, r) + return + } + + w.Header().Set("Content-Encoding", "gzip") + + gz := gzPool.Get().(*gzip.Writer) + defer gzPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r) + }) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/handler.go b/vendor/github.com/ethereum/go-ethereum/rpc/handler.go new file mode 100644 index 000000000..8a4e480ee --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/handler.go @@ -0,0 +1,397 @@ +// Copyright 2019 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 rpc + +import ( + "context" + "encoding/json" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum/log" +) + +// handler handles JSON-RPC messages. There is one handler per connection. Note that +// handler is not safe for concurrent use. Message handling never blocks indefinitely +// because RPCs are processed on background goroutines launched by handler. +// +// The entry points for incoming messages are: +// +// h.handleMsg(message) +// h.handleBatch(message) +// +// Outgoing calls use the requestOp struct. Register the request before sending it +// on the connection: +// +// op := &requestOp{ids: ...} +// h.addRequestOp(op) +// +// Now send the request, then wait for the reply to be delivered through handleMsg: +// +// if err := op.wait(...); err != nil { +// h.removeRequestOp(op) // timeout, etc. +// } +// +type handler struct { + reg *serviceRegistry + unsubscribeCb *callback + idgen func() ID // subscription ID generator + respWait map[string]*requestOp // active client requests + clientSubs map[string]*ClientSubscription // active client subscriptions + callWG sync.WaitGroup // pending call goroutines + rootCtx context.Context // canceled by close() + cancelRoot func() // cancel function for rootCtx + conn jsonWriter // where responses will be sent + log log.Logger + allowSubscribe bool + + subLock sync.Mutex + serverSubs map[ID]*Subscription +} + +type callProc struct { + ctx context.Context + notifiers []*Notifier +} + +func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *serviceRegistry) *handler { + rootCtx, cancelRoot := context.WithCancel(connCtx) + h := &handler{ + reg: reg, + idgen: idgen, + conn: conn, + respWait: make(map[string]*requestOp), + clientSubs: make(map[string]*ClientSubscription), + rootCtx: rootCtx, + cancelRoot: cancelRoot, + allowSubscribe: true, + serverSubs: make(map[ID]*Subscription), + log: log.Root(), + } + if conn.RemoteAddr() != "" { + h.log = h.log.New("conn", conn.RemoteAddr()) + } + h.unsubscribeCb = newCallback(reflect.Value{}, reflect.ValueOf(h.unsubscribe)) + return h +} + +// handleBatch executes all messages in a batch and returns the responses. +func (h *handler) handleBatch(msgs []*jsonrpcMessage) { + // Emit error response for empty batches: + if len(msgs) == 0 { + h.startCallProc(func(cp *callProc) { + h.conn.Write(cp.ctx, errorMessage(&invalidRequestError{"empty batch"})) + }) + return + } + + // Handle non-call messages first: + calls := make([]*jsonrpcMessage, 0, len(msgs)) + for _, msg := range msgs { + if handled := h.handleImmediate(msg); !handled { + calls = append(calls, msg) + } + } + if len(calls) == 0 { + return + } + // Process calls on a goroutine because they may block indefinitely: + h.startCallProc(func(cp *callProc) { + answers := make([]*jsonrpcMessage, 0, len(msgs)) + for _, msg := range calls { + if answer := h.handleCallMsg(cp, msg); answer != nil { + answers = append(answers, answer) + } + } + h.addSubscriptions(cp.notifiers) + if len(answers) > 0 { + h.conn.Write(cp.ctx, answers) + } + for _, n := range cp.notifiers { + n.activate() + } + }) +} + +// handleMsg handles a single message. +func (h *handler) handleMsg(msg *jsonrpcMessage) { + if ok := h.handleImmediate(msg); ok { + return + } + h.startCallProc(func(cp *callProc) { + answer := h.handleCallMsg(cp, msg) + h.addSubscriptions(cp.notifiers) + if answer != nil { + h.conn.Write(cp.ctx, answer) + } + for _, n := range cp.notifiers { + n.activate() + } + }) +} + +// close cancels all requests except for inflightReq and waits for +// call goroutines to shut down. +func (h *handler) close(err error, inflightReq *requestOp) { + h.cancelAllRequests(err, inflightReq) + h.callWG.Wait() + h.cancelRoot() + h.cancelServerSubscriptions(err) +} + +// addRequestOp registers a request operation. +func (h *handler) addRequestOp(op *requestOp) { + for _, id := range op.ids { + h.respWait[string(id)] = op + } +} + +// removeRequestOps stops waiting for the given request IDs. +func (h *handler) removeRequestOp(op *requestOp) { + for _, id := range op.ids { + delete(h.respWait, string(id)) + } +} + +// cancelAllRequests unblocks and removes pending requests and active subscriptions. +func (h *handler) cancelAllRequests(err error, inflightReq *requestOp) { + didClose := make(map[*requestOp]bool) + if inflightReq != nil { + didClose[inflightReq] = true + } + + for id, op := range h.respWait { + // Remove the op so that later calls will not close op.resp again. + delete(h.respWait, id) + + if !didClose[op] { + op.err = err + close(op.resp) + didClose[op] = true + } + } + for id, sub := range h.clientSubs { + delete(h.clientSubs, id) + sub.quitWithError(err, false) + } +} + +func (h *handler) addSubscriptions(nn []*Notifier) { + h.subLock.Lock() + defer h.subLock.Unlock() + + for _, n := range nn { + if sub := n.takeSubscription(); sub != nil { + h.serverSubs[sub.ID] = sub + } + } +} + +// cancelServerSubscriptions removes all subscriptions and closes their error channels. +func (h *handler) cancelServerSubscriptions(err error) { + h.subLock.Lock() + defer h.subLock.Unlock() + + for id, s := range h.serverSubs { + s.err <- err + close(s.err) + delete(h.serverSubs, id) + } +} + +// startCallProc runs fn in a new goroutine and starts tracking it in the h.calls wait group. +func (h *handler) startCallProc(fn func(*callProc)) { + h.callWG.Add(1) + go func() { + ctx, cancel := context.WithCancel(h.rootCtx) + defer h.callWG.Done() + defer cancel() + fn(&callProc{ctx: ctx}) + }() +} + +// handleImmediate executes non-call messages. It returns false if the message is a +// call or requires a reply. +func (h *handler) handleImmediate(msg *jsonrpcMessage) bool { + start := time.Now() + switch { + case msg.isNotification(): + if strings.HasSuffix(msg.Method, notificationMethodSuffix) { + h.handleSubscriptionResult(msg) + return true + } + return false + case msg.isResponse(): + h.handleResponse(msg) + h.log.Trace("Handled RPC response", "reqid", idForLog{msg.ID}, "t", time.Since(start)) + return true + default: + return false + } +} + +// handleSubscriptionResult processes subscription notifications. +func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) { + var result subscriptionResult + if err := json.Unmarshal(msg.Params, &result); err != nil { + h.log.Debug("Dropping invalid subscription message") + return + } + if h.clientSubs[result.ID] != nil { + h.clientSubs[result.ID].deliver(result.Result) + } +} + +// handleResponse processes method call responses. +func (h *handler) handleResponse(msg *jsonrpcMessage) { + op := h.respWait[string(msg.ID)] + if op == nil { + h.log.Debug("Unsolicited RPC response", "reqid", idForLog{msg.ID}) + return + } + delete(h.respWait, string(msg.ID)) + // For normal responses, just forward the reply to Call/BatchCall. + if op.sub == nil { + op.resp <- msg + return + } + // For subscription responses, start the subscription if the server + // indicates success. EthSubscribe gets unblocked in either case through + // the op.resp channel. + defer close(op.resp) + if msg.Error != nil { + op.err = msg.Error + return + } + if op.err = json.Unmarshal(msg.Result, &op.sub.subid); op.err == nil { + go op.sub.start() + h.clientSubs[op.sub.subid] = op.sub + } +} + +// handleCallMsg executes a call message and returns the answer. +func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + start := time.Now() + switch { + case msg.isNotification(): + h.handleCall(ctx, msg) + h.log.Debug("Served "+msg.Method, "t", time.Since(start)) + return nil + case msg.isCall(): + resp := h.handleCall(ctx, msg) + if resp.Error != nil { + h.log.Warn("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start), "err", resp.Error.Message) + } else { + h.log.Debug("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start)) + } + return resp + case msg.hasValidID(): + return msg.errorResponse(&invalidRequestError{"invalid request"}) + default: + return errorMessage(&invalidRequestError{"invalid request"}) + } +} + +// handleCall processes method calls. +func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + if msg.isSubscribe() { + return h.handleSubscribe(cp, msg) + } + var callb *callback + if msg.isUnsubscribe() { + callb = h.unsubscribeCb + } else { + callb = h.reg.callback(msg.Method) + } + if callb == nil { + return msg.errorResponse(&methodNotFoundError{method: msg.Method}) + } + args, err := parsePositionalArguments(msg.Params, callb.argTypes) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + + return h.runMethod(cp.ctx, msg, callb, args) +} + +// handleSubscribe processes *_subscribe method calls. +func (h *handler) handleSubscribe(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage { + if !h.allowSubscribe { + return msg.errorResponse(ErrNotificationsUnsupported) + } + + // Subscription method name is first argument. + name, err := parseSubscriptionName(msg.Params) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + namespace := msg.namespace() + callb := h.reg.subscription(namespace, name) + if callb == nil { + return msg.errorResponse(&subscriptionNotFoundError{namespace, name}) + } + + // Parse subscription name arg too, but remove it before calling the callback. + argTypes := append([]reflect.Type{stringType}, callb.argTypes...) + args, err := parsePositionalArguments(msg.Params, argTypes) + if err != nil { + return msg.errorResponse(&invalidParamsError{err.Error()}) + } + args = args[1:] + + // Install notifier in context so the subscription handler can find it. + n := &Notifier{h: h, namespace: namespace} + cp.notifiers = append(cp.notifiers, n) + ctx := context.WithValue(cp.ctx, notifierKey{}, n) + + return h.runMethod(ctx, msg, callb, args) +} + +// runMethod runs the Go callback for an RPC method. +func (h *handler) runMethod(ctx context.Context, msg *jsonrpcMessage, callb *callback, args []reflect.Value) *jsonrpcMessage { + result, err := callb.call(ctx, msg.Method, args) + if err != nil { + return msg.errorResponse(err) + } + return msg.response(result) +} + +// unsubscribe is the callback function for all *_unsubscribe calls. +func (h *handler) unsubscribe(ctx context.Context, id ID) (bool, error) { + h.subLock.Lock() + defer h.subLock.Unlock() + + s := h.serverSubs[id] + if s == nil { + return false, ErrSubscriptionNotFound + } + close(s.err) + delete(h.serverSubs, id) + return true, nil +} + +type idForLog struct{ json.RawMessage } + +func (id idForLog) String() string { + if s, err := strconv.Unquote(string(id.RawMessage)); err == nil { + return s + } + return string(id.RawMessage) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/http.go b/vendor/github.com/ethereum/go-ethereum/rpc/http.go index 674166fb3..2c0cb5edb 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/http.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/http.go @@ -36,39 +36,40 @@ import ( ) const ( - maxRequestContentLength = 1024 * 512 + maxRequestContentLength = 1024 * 1024 * 5 + contentType = "application/json" ) -var ( - // https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 - acceptedContentTypes = []string{"application/json", "application/json-rpc", "application/jsonrequest"} - contentType = acceptedContentTypes[0] - nullAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:0") -) +// https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 +var acceptedContentTypes = []string{contentType, "application/json-rpc", "application/jsonrequest"} type httpConn struct { client *http.Client req *http.Request closeOnce sync.Once - closed chan struct{} + closed chan interface{} } // httpConn is treated specially by Client. -func (hc *httpConn) LocalAddr() net.Addr { return nullAddr } -func (hc *httpConn) RemoteAddr() net.Addr { return nullAddr } -func (hc *httpConn) SetReadDeadline(time.Time) error { return nil } -func (hc *httpConn) SetWriteDeadline(time.Time) error { return nil } -func (hc *httpConn) SetDeadline(time.Time) error { return nil } -func (hc *httpConn) Write([]byte) (int, error) { panic("Write called") } - -func (hc *httpConn) Read(b []byte) (int, error) { - <-hc.closed - return 0, io.EOF +func (hc *httpConn) Write(context.Context, interface{}) error { + panic("Write called on httpConn") } -func (hc *httpConn) Close() error { +func (hc *httpConn) RemoteAddr() string { + return hc.req.URL.String() +} + +func (hc *httpConn) Read() ([]*jsonrpcMessage, bool, error) { + <-hc.closed + return nil, false, io.EOF +} + +func (hc *httpConn) Close() { hc.closeOnce.Do(func() { close(hc.closed) }) - return nil +} + +func (hc *httpConn) Closed() <-chan interface{} { + return hc.closed } // HTTPTimeouts represents the configuration params for the HTTP RPC server. @@ -114,8 +115,8 @@ func DialHTTPWithClient(endpoint string, client *http.Client) (*Client, error) { req.Header.Set("Accept", contentType) initctx := context.Background() - return newClient(initctx, func(context.Context) (net.Conn, error) { - return &httpConn{client: client, req: req, closed: make(chan struct{})}, nil + return newClient(initctx, func(context.Context) (ServerCodec, error) { + return &httpConn{client: client, req: req, closed: make(chan interface{})}, nil }) } @@ -184,24 +185,38 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos return resp.Body, nil } -// httpReadWriteNopCloser wraps a io.Reader and io.Writer with a NOP Close method. -type httpReadWriteNopCloser struct { +// httpServerConn turns a HTTP connection into a Conn. +type httpServerConn struct { io.Reader io.Writer + r *http.Request } -// Close does nothing and returns always nil -func (t *httpReadWriteNopCloser) Close() error { - return nil +func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec { + body := io.LimitReader(r.Body, maxRequestContentLength) + conn := &httpServerConn{Reader: body, Writer: w, r: r} + return NewJSONCodec(conn) } +// Close does nothing and always returns nil. +func (t *httpServerConn) Close() error { return nil } + +// RemoteAddr returns the peer address of the underlying connection. +func (t *httpServerConn) RemoteAddr() string { + return t.r.RemoteAddr +} + +// SetWriteDeadline does nothing and always returns nil. +func (t *httpServerConn) SetWriteDeadline(time.Time) error { return nil } + // NewHTTPServer creates a new HTTP RPC server around an API provider. // // Deprecated: Server implements http.Handler -func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv *Server) *http.Server { +func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv http.Handler) *http.Server { // Wrap the CORS-handler within a host-handler handler := newCorsHandler(srv, cors) handler = newVHostHandler(vhosts, handler) + handler = newGzipHandler(handler) // Make sure timeout values are meaningful if timeouts.ReadTimeout < time.Second { @@ -226,7 +241,7 @@ func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv *S } // ServeHTTP serves JSON-RPC requests over HTTP. -func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Permit dumb empty requests for remote health-checks (AWS) if r.Method == http.MethodGet && r.ContentLength == 0 && r.URL.RawQuery == "" { return @@ -249,12 +264,10 @@ func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, "Origin", origin) } - body := io.LimitReader(r.Body, maxRequestContentLength) - codec := NewJSONCodec(&httpReadWriteNopCloser{body, w}) - defer codec.Close() - w.Header().Set("content-type", contentType) - srv.ServeSingleRequest(ctx, codec, OptionMethodInvocation) + codec := newHTTPServerConn(r, w) + defer codec.Close() + s.serveSingleRequest(ctx, codec) } // validateRequest returns a non-zero response code and error message if the @@ -284,7 +297,7 @@ func validateRequest(r *http.Request) (int, error) { return http.StatusUnsupportedMediaType, err } -func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler { +func newCorsHandler(srv http.Handler, allowedOrigins []string) http.Handler { // disable CORS support if user has not specified a custom CORS configuration if len(allowedOrigins) == 0 { return srv diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go b/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go index cbe65d10e..c4456cfc4 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/inproc.go @@ -24,10 +24,10 @@ import ( // DialInProc attaches an in-process connection to the given RPC server. func DialInProc(handler *Server) *Client { initctx := context.Background() - c, _ := newClient(initctx, func(context.Context) (net.Conn, error) { + c, _ := newClient(initctx, func(context.Context) (ServerCodec, error) { p1, p2 := net.Pipe() go handler.ServeCodec(NewJSONCodec(p1), OptionMethodInvocation|OptionSubscriptions) - return p2, nil + return NewJSONCodec(p2), nil }) return c } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go b/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go index 4cce1cf74..ad8ce0309 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/ipc.go @@ -25,17 +25,17 @@ import ( ) // ServeListener accepts connections on l, serving JSON-RPC on them. -func (srv *Server) ServeListener(l net.Listener) error { +func (s *Server) ServeListener(l net.Listener) error { for { conn, err := l.Accept() if netutil.IsTemporaryError(err) { - log.Warn("IPC accept error", "err", err) + log.Warn("RPC accept error", "err", err) continue } else if err != nil { return err } - log.Trace("IPC accepted connection") - go srv.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions) + log.Trace("Accepted RPC connection", "conn", conn.RemoteAddr()) + go s.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions) } } @@ -46,7 +46,11 @@ func (srv *Server) ServeListener(l net.Listener) error { // The context is used for the initial connection establishment. It does not // affect subsequent interactions with the client. func DialIPC(ctx context.Context, endpoint string) (*Client, error) { - return newClient(ctx, func(ctx context.Context) (net.Conn, error) { - return newIPCConnection(ctx, endpoint) + return newClient(ctx, func(ctx context.Context) (ServerCodec, error) { + conn, err := newIPCConnection(ctx, endpoint) + if err != nil { + return nil, err + } + return NewJSONCodec(conn), err }) } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/ipc_js.go b/vendor/github.com/ethereum/go-ethereum/rpc/ipc_js.go index eceef050e..7e7554a76 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/ipc_js.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/ipc_js.go @@ -1,4 +1,4 @@ -// Copyright 2015 The go-ethereum Authors +// Copyright 2018 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/ipc_unix.go b/vendor/github.com/ethereum/go-ethereum/rpc/ipc_unix.go index 707b47fd7..f4690cc0a 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/ipc_unix.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/ipc_unix.go @@ -28,20 +28,10 @@ import ( "github.com/ethereum/go-ethereum/log" ) -/* -#include - -int max_socket_path_size() { -struct sockaddr_un s; -return sizeof(s.sun_path); -} -*/ -import "C" - // ipcListen will create a Unix socket on the given endpoint. func ipcListen(endpoint string) (net.Listener, error) { - if len(endpoint) > int(C.max_socket_path_size()) { - log.Warn(fmt.Sprintf("The ipc endpoint is longer than %d characters. ", C.max_socket_path_size()), + if len(endpoint) > int(max_path_size) { + log.Warn(fmt.Sprintf("The ipc endpoint is longer than %d characters. ", max_path_size), "endpoint", endpoint) } @@ -60,5 +50,5 @@ func ipcListen(endpoint string) (net.Listener, error) { // newIPCConnection will connect to a Unix socket on the given endpoint. func newIPCConnection(ctx context.Context, endpoint string) (net.Conn, error) { - return dialContext(ctx, "unix", endpoint) + return new(net.Dialer).DialContext(ctx, "unix", endpoint) } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/json.go b/vendor/github.com/ethereum/go-ethereum/rpc/json.go index a523eeb8e..75c221038 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/json.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/json.go @@ -18,36 +18,104 @@ package rpc import ( "bytes" + "context" "encoding/json" + "errors" "fmt" "io" "reflect" - "strconv" "strings" "sync" - - "github.com/ethereum/go-ethereum/log" + "time" ) const ( - jsonrpcVersion = "2.0" + vsn = "2.0" serviceMethodSeparator = "_" subscribeMethodSuffix = "_subscribe" unsubscribeMethodSuffix = "_unsubscribe" notificationMethodSuffix = "_subscription" + + defaultWriteTimeout = 10 * time.Second // used if context has no deadline ) -type jsonRequest struct { - Method string `json:"method"` - Version string `json:"jsonrpc"` - Id json.RawMessage `json:"id,omitempty"` - Payload json.RawMessage `json:"params,omitempty"` +var null = json.RawMessage("null") + +type subscriptionResult struct { + ID string `json:"subscription"` + Result json.RawMessage `json:"result,omitempty"` } -type jsonSuccessResponse struct { - Version string `json:"jsonrpc"` - Id interface{} `json:"id,omitempty"` - Result interface{} `json:"result"` +// A value of this type can a JSON-RPC request, notification, successful response or +// error response. Which one it is depends on the fields. +type jsonrpcMessage struct { + Version string `json:"jsonrpc,omitempty"` + ID json.RawMessage `json:"id,omitempty"` + Method string `json:"method,omitempty"` + Params json.RawMessage `json:"params,omitempty"` + Error *jsonError `json:"error,omitempty"` + Result json.RawMessage `json:"result,omitempty"` +} + +func (msg *jsonrpcMessage) isNotification() bool { + return msg.ID == nil && msg.Method != "" +} + +func (msg *jsonrpcMessage) isCall() bool { + return msg.hasValidID() && msg.Method != "" +} + +func (msg *jsonrpcMessage) isResponse() bool { + return msg.hasValidID() && msg.Method == "" && msg.Params == nil && (msg.Result != nil || msg.Error != nil) +} + +func (msg *jsonrpcMessage) hasValidID() bool { + return len(msg.ID) > 0 && msg.ID[0] != '{' && msg.ID[0] != '[' +} + +func (msg *jsonrpcMessage) isSubscribe() bool { + return strings.HasSuffix(msg.Method, subscribeMethodSuffix) +} + +func (msg *jsonrpcMessage) isUnsubscribe() bool { + return strings.HasSuffix(msg.Method, unsubscribeMethodSuffix) +} + +func (msg *jsonrpcMessage) namespace() string { + elem := strings.SplitN(msg.Method, serviceMethodSeparator, 2) + return elem[0] +} + +func (msg *jsonrpcMessage) String() string { + b, _ := json.Marshal(msg) + return string(b) +} + +func (msg *jsonrpcMessage) errorResponse(err error) *jsonrpcMessage { + resp := errorMessage(err) + resp.ID = msg.ID + return resp +} + +func (msg *jsonrpcMessage) response(result interface{}) *jsonrpcMessage { + enc, err := json.Marshal(result) + if err != nil { + // TODO: wrap with 'internal server error' + return msg.errorResponse(err) + } + return &jsonrpcMessage{Version: vsn, ID: msg.ID, Result: enc} +} + +func errorMessage(err error) *jsonrpcMessage { + msg := &jsonrpcMessage{Version: vsn, ID: null, Error: &jsonError{ + Code: defaultErrorCode, + Message: err.Error(), + }} + ec, ok := err.(Error) + if ok { + msg.Error.Code = ec.ErrorCode() + } + return msg } type jsonError struct { @@ -56,35 +124,6 @@ type jsonError struct { Data interface{} `json:"data,omitempty"` } -type jsonErrResponse struct { - Version string `json:"jsonrpc"` - Id interface{} `json:"id,omitempty"` - Error jsonError `json:"error"` -} - -type jsonSubscription struct { - Subscription string `json:"subscription"` - Result interface{} `json:"result,omitempty"` -} - -type jsonNotification struct { - Version string `json:"jsonrpc"` - Method string `json:"method"` - Params jsonSubscription `json:"params"` -} - -// jsonCodec reads and writes JSON-RPC messages to the underlying connection. It -// also has support for parsing arguments and serializing (result) objects. -type jsonCodec struct { - closer sync.Once // close closed channel once - closed chan interface{} // closed on Close - decMu sync.Mutex // guards the decoder - decode func(v interface{}) error // decoder to allow multiple transports - encMu sync.Mutex // guards the encoder - encode func(v interface{}) error // encoder to allow multiple transports - rw io.ReadWriteCloser // connection -} - func (err *jsonError) Error() string { if err.Message == "" { return fmt.Sprintf("json-rpc error %d", err.Code) @@ -96,34 +135,131 @@ func (err *jsonError) ErrorCode() int { return err.Code } -// NewCodec creates a new RPC server codec with support for JSON-RPC 2.0 based -// on explicitly given encoding and decoding methods. -func NewCodec(rwc io.ReadWriteCloser, encode, decode func(v interface{}) error) ServerCodec { - return &jsonCodec{ +// Conn is a subset of the methods of net.Conn which are sufficient for ServerCodec. +type Conn interface { + io.ReadWriteCloser + SetWriteDeadline(time.Time) error +} + +type deadlineCloser interface { + io.Closer + SetWriteDeadline(time.Time) error +} + +// ConnRemoteAddr wraps the RemoteAddr operation, which returns a description +// of the peer address of a connection. If a Conn also implements ConnRemoteAddr, this +// description is used in log messages. +type ConnRemoteAddr interface { + RemoteAddr() string +} + +// connWithRemoteAddr overrides the remote address of a connection. +type connWithRemoteAddr struct { + Conn + addr string +} + +func (c connWithRemoteAddr) RemoteAddr() string { return c.addr } + +// jsonCodec reads and writes JSON-RPC messages to the underlying connection. It also has +// support for parsing arguments and serializing (result) objects. +type jsonCodec struct { + remoteAddr string + closer sync.Once // close closed channel once + closed chan interface{} // closed on Close + decode func(v interface{}) error // decoder to allow multiple transports + encMu sync.Mutex // guards the encoder + encode func(v interface{}) error // encoder to allow multiple transports + conn deadlineCloser +} + +func newCodec(conn deadlineCloser, encode, decode func(v interface{}) error) ServerCodec { + codec := &jsonCodec{ closed: make(chan interface{}), encode: encode, decode: decode, - rw: rwc, + conn: conn, } + if ra, ok := conn.(ConnRemoteAddr); ok { + codec.remoteAddr = ra.RemoteAddr() + } + return codec } -// NewJSONCodec creates a new RPC server codec with support for JSON-RPC 2.0. -func NewJSONCodec(rwc io.ReadWriteCloser) ServerCodec { - enc := json.NewEncoder(rwc) - dec := json.NewDecoder(rwc) +// NewJSONCodec creates a codec that reads from the given connection. If conn implements +// ConnRemoteAddr, log messages will use it to include the remote address of the +// connection. +func NewJSONCodec(conn Conn) ServerCodec { + enc := json.NewEncoder(conn) + dec := json.NewDecoder(conn) dec.UseNumber() + return newCodec(conn, enc.Encode, dec.Decode) +} - return &jsonCodec{ - closed: make(chan interface{}), - encode: enc.Encode, - decode: dec.Decode, - rw: rwc, +func (c *jsonCodec) RemoteAddr() string { + return c.remoteAddr +} + +func (c *jsonCodec) Read() (msg []*jsonrpcMessage, batch bool, err error) { + // Decode the next JSON object in the input stream. + // This verifies basic syntax, etc. + var rawmsg json.RawMessage + if err := c.decode(&rawmsg); err != nil { + return nil, false, err } + msg, batch = parseMessage(rawmsg) + return msg, batch, nil +} + +// Write sends a message to client. +func (c *jsonCodec) Write(ctx context.Context, v interface{}) error { + c.encMu.Lock() + defer c.encMu.Unlock() + + deadline, ok := ctx.Deadline() + if !ok { + deadline = time.Now().Add(defaultWriteTimeout) + } + c.conn.SetWriteDeadline(deadline) + return c.encode(v) +} + +// Close the underlying connection +func (c *jsonCodec) Close() { + c.closer.Do(func() { + close(c.closed) + c.conn.Close() + }) +} + +// Closed returns a channel which will be closed when Close is called +func (c *jsonCodec) Closed() <-chan interface{} { + return c.closed +} + +// parseMessage parses raw bytes as a (batch of) JSON-RPC message(s). There are no error +// checks in this function because the raw message has already been syntax-checked when it +// is called. Any non-JSON-RPC messages in the input return the zero value of +// jsonrpcMessage. +func parseMessage(raw json.RawMessage) ([]*jsonrpcMessage, bool) { + if !isBatch(raw) { + msgs := []*jsonrpcMessage{{}} + json.Unmarshal(raw, &msgs[0]) + return msgs, false + } + dec := json.NewDecoder(bytes.NewReader(raw)) + dec.Token() // skip '[' + var msgs []*jsonrpcMessage + for dec.More() { + msgs = append(msgs, new(jsonrpcMessage)) + dec.Decode(&msgs[len(msgs)-1]) + } + return msgs, true } // isBatch returns true when the first non-whitespace characters is '[' -func isBatch(msg json.RawMessage) bool { - for _, c := range msg { +func isBatch(raw json.RawMessage) bool { + for _, c := range raw { // skip insignificant whitespace (http://www.ietf.org/rfc/rfc4627.txt) if c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d { continue @@ -133,231 +269,67 @@ func isBatch(msg json.RawMessage) bool { return false } -// ReadRequestHeaders will read new requests without parsing the arguments. It will -// return a collection of requests, an indication if these requests are in batch -// form or an error when the incoming message could not be read/parsed. -func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, Error) { - c.decMu.Lock() - defer c.decMu.Unlock() - - var incomingMsg json.RawMessage - if err := c.decode(&incomingMsg); err != nil { - return nil, false, &invalidRequestError{err.Error()} - } - if isBatch(incomingMsg) { - return parseBatchRequest(incomingMsg) - } - return parseRequest(incomingMsg) -} - -// checkReqId returns an error when the given reqId isn't valid for RPC method calls. -// valid id's are strings, numbers or null -func checkReqId(reqId json.RawMessage) error { - if len(reqId) == 0 { - return fmt.Errorf("missing request id") - } - if _, err := strconv.ParseFloat(string(reqId), 64); err == nil { - return nil - } - var str string - if err := json.Unmarshal(reqId, &str); err == nil { - return nil - } - return fmt.Errorf("invalid request id") -} - -// parseRequest will parse a single request from the given RawMessage. It will return -// the parsed request, an indication if the request was a batch or an error when -// the request could not be parsed. -func parseRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { - var in jsonRequest - if err := json.Unmarshal(incomingMsg, &in); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - if err := checkReqId(in.Id); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - // subscribe are special, they will always use `subscribeMethod` as first param in the payload - if strings.HasSuffix(in.Method, subscribeMethodSuffix) { - reqs := []rpcRequest{{id: &in.Id, isPubSub: true}} - if len(in.Payload) > 0 { - // first param must be subscription name - var subscribeMethod [1]string - if err := json.Unmarshal(in.Payload, &subscribeMethod); err != nil { - log.Debug(fmt.Sprintf("Unable to parse subscription method: %v\n", err)) - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - reqs[0].service, reqs[0].method = strings.TrimSuffix(in.Method, subscribeMethodSuffix), subscribeMethod[0] - reqs[0].params = in.Payload - return reqs, false, nil - } - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - if strings.HasSuffix(in.Method, unsubscribeMethodSuffix) { - return []rpcRequest{{id: &in.Id, isPubSub: true, - method: in.Method, params: in.Payload}}, false, nil - } - - elems := strings.Split(in.Method, serviceMethodSeparator) - if len(elems) != 2 { - return nil, false, &methodNotFoundError{in.Method, ""} - } - - // regular RPC call - if len(in.Payload) == 0 { - return []rpcRequest{{service: elems[0], method: elems[1], id: &in.Id}}, false, nil - } - - return []rpcRequest{{service: elems[0], method: elems[1], id: &in.Id, params: in.Payload}}, false, nil -} - -// parseBatchRequest will parse a batch request into a collection of requests from the given RawMessage, an indication -// if the request was a batch or an error when the request could not be read. -func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error) { - var in []jsonRequest - if err := json.Unmarshal(incomingMsg, &in); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - requests := make([]rpcRequest, len(in)) - for i, r := range in { - if err := checkReqId(r.Id); err != nil { - return nil, false, &invalidMessageError{err.Error()} - } - - id := &in[i].Id - - // subscribe are special, they will always use `subscriptionMethod` as first param in the payload - if strings.HasSuffix(r.Method, subscribeMethodSuffix) { - requests[i] = rpcRequest{id: id, isPubSub: true} - if len(r.Payload) > 0 { - // first param must be subscription name - var subscribeMethod [1]string - if err := json.Unmarshal(r.Payload, &subscribeMethod); err != nil { - log.Debug(fmt.Sprintf("Unable to parse subscription method: %v\n", err)) - return nil, false, &invalidRequestError{"Unable to parse subscription request"} - } - - requests[i].service, requests[i].method = strings.TrimSuffix(r.Method, subscribeMethodSuffix), subscribeMethod[0] - requests[i].params = r.Payload - continue - } - - return nil, true, &invalidRequestError{"Unable to parse (un)subscribe request arguments"} - } - - if strings.HasSuffix(r.Method, unsubscribeMethodSuffix) { - requests[i] = rpcRequest{id: id, isPubSub: true, method: r.Method, params: r.Payload} - continue - } - - if len(r.Payload) == 0 { - requests[i] = rpcRequest{id: id, params: nil} - } else { - requests[i] = rpcRequest{id: id, params: r.Payload} - } - if elem := strings.Split(r.Method, serviceMethodSeparator); len(elem) == 2 { - requests[i].service, requests[i].method = elem[0], elem[1] - } else { - requests[i].err = &methodNotFoundError{r.Method, ""} - } - } - - return requests, true, nil -} - -// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given -// types. It returns the parsed values or an error when the parsing failed. -func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) { - if args, ok := params.(json.RawMessage); !ok { - return nil, &invalidParamsError{"Invalid params supplied"} - } else { - return parsePositionalArguments(args, argTypes) - } -} - // parsePositionalArguments tries to parse the given args to an array of values with the // given types. It returns the parsed values or an error when the args could not be // parsed. Missing optional arguments are returned as reflect.Zero values. -func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, Error) { - // Read beginning of the args array. +func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, error) { dec := json.NewDecoder(bytes.NewReader(rawArgs)) - if tok, _ := dec.Token(); tok != json.Delim('[') { - return nil, &invalidParamsError{"non-array args"} - } - // Read args. - args := make([]reflect.Value, 0, len(types)) - for i := 0; dec.More(); i++ { - if i >= len(types) { - return nil, &invalidParamsError{fmt.Sprintf("too many arguments, want at most %d", len(types))} + var args []reflect.Value + tok, err := dec.Token() + switch { + case err == io.EOF || tok == nil && err == nil: + // "params" is optional and may be empty. Also allow "params":null even though it's + // not in the spec because our own client used to send it. + case err != nil: + return nil, err + case tok == json.Delim('['): + // Read argument array. + if args, err = parseArgumentArray(dec, types); err != nil { + return nil, err } - argval := reflect.New(types[i]) - if err := dec.Decode(argval.Interface()); err != nil { - return nil, &invalidParamsError{fmt.Sprintf("invalid argument %d: %v", i, err)} - } - if argval.IsNil() && types[i].Kind() != reflect.Ptr { - return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)} - } - args = append(args, argval.Elem()) - } - // Read end of args array. - if _, err := dec.Token(); err != nil { - return nil, &invalidParamsError{err.Error()} + default: + return nil, errors.New("non-array args") } // Set any missing args to nil. for i := len(args); i < len(types); i++ { if types[i].Kind() != reflect.Ptr { - return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)} + return nil, fmt.Errorf("missing value for required argument %d", i) } args = append(args, reflect.Zero(types[i])) } return args, nil } -// CreateResponse will create a JSON-RPC success response with the given id and reply as result. -func (c *jsonCodec) CreateResponse(id interface{}, reply interface{}) interface{} { - return &jsonSuccessResponse{Version: jsonrpcVersion, Id: id, Result: reply} +func parseArgumentArray(dec *json.Decoder, types []reflect.Type) ([]reflect.Value, error) { + args := make([]reflect.Value, 0, len(types)) + for i := 0; dec.More(); i++ { + if i >= len(types) { + return args, fmt.Errorf("too many arguments, want at most %d", len(types)) + } + argval := reflect.New(types[i]) + if err := dec.Decode(argval.Interface()); err != nil { + return args, fmt.Errorf("invalid argument %d: %v", i, err) + } + if argval.IsNil() && types[i].Kind() != reflect.Ptr { + return args, fmt.Errorf("missing value for required argument %d", i) + } + args = append(args, argval.Elem()) + } + // Read end of args array. + _, err := dec.Token() + return args, err } -// CreateErrorResponse will create a JSON-RPC error response with the given id and error. -func (c *jsonCodec) CreateErrorResponse(id interface{}, err Error) interface{} { - return &jsonErrResponse{Version: jsonrpcVersion, Id: id, Error: jsonError{Code: err.ErrorCode(), Message: err.Error()}} -} - -// CreateErrorResponseWithInfo will create a JSON-RPC error response with the given id and error. -// info is optional and contains additional information about the error. When an empty string is passed it is ignored. -func (c *jsonCodec) CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} { - return &jsonErrResponse{Version: jsonrpcVersion, Id: id, - Error: jsonError{Code: err.ErrorCode(), Message: err.Error(), Data: info}} -} - -// CreateNotification will create a JSON-RPC notification with the given subscription id and event as params. -func (c *jsonCodec) CreateNotification(subid, namespace string, event interface{}) interface{} { - return &jsonNotification{Version: jsonrpcVersion, Method: namespace + notificationMethodSuffix, - Params: jsonSubscription{Subscription: subid, Result: event}} -} - -// Write message to client -func (c *jsonCodec) Write(res interface{}) error { - c.encMu.Lock() - defer c.encMu.Unlock() - - return c.encode(res) -} - -// Close the underlying connection -func (c *jsonCodec) Close() { - c.closer.Do(func() { - close(c.closed) - c.rw.Close() - }) -} - -// Closed returns a channel which will be closed when Close is called -func (c *jsonCodec) Closed() <-chan interface{} { - return c.closed +// parseSubscriptionName extracts the subscription name from an encoded argument array. +func parseSubscriptionName(rawArgs json.RawMessage) (string, error) { + dec := json.NewDecoder(bytes.NewReader(rawArgs)) + if tok, _ := dec.Token(); tok != json.Delim('[') { + return "", errors.New("non-array args") + } + v, _ := dec.Token() + method, ok := v.(string) + if !ok { + return "", errors.New("expected subscription name as first argument") + } + return method, nil } diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/server.go b/vendor/github.com/ethereum/go-ethereum/rpc/server.go index 214e1d3ed..5a92847f2 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/server.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/server.go @@ -18,11 +18,7 @@ package rpc import ( "context" - "fmt" - "reflect" - "runtime" - "strings" - "sync" + "io" "sync/atomic" mapset "github.com/deckarep/golang-set" @@ -31,7 +27,9 @@ import ( const MetadataApi = "rpc" -// CodecOption specifies which type of messages this codec supports +// CodecOption specifies which type of messages a codec supports. +// +// Deprecated: this option is no longer honored by Server. type CodecOption int const ( @@ -42,22 +40,94 @@ const ( OptionSubscriptions = 1 << iota // support pub sub ) -// NewServer will create a new server instance with no registered handlers. -func NewServer() *Server { - server := &Server{ - services: make(serviceRegistry), - codecs: mapset.NewSet(), - run: 1, - } +// Server is an RPC server. +type Server struct { + services serviceRegistry + idgen func() ID + run int32 + codecs mapset.Set +} - // register a default service which will provide meta information about the RPC service such as the services and - // methods it offers. +// NewServer creates a new server instance with no registered handlers. +func NewServer() *Server { + server := &Server{idgen: randomIDGenerator(), codecs: mapset.NewSet(), run: 1} + // Register the default service providing meta information about the RPC service such + // as the services and methods it offers. rpcService := &RPCService{server} server.RegisterName(MetadataApi, rpcService) - return server } +// RegisterName creates a service for the given receiver type under the given name. When no +// methods on the given receiver match the criteria to be either a RPC method or a +// subscription an error is returned. Otherwise a new service is created and added to the +// service collection this server provides to clients. +func (s *Server) RegisterName(name string, receiver interface{}) error { + return s.services.registerName(name, receiver) +} + +// ServeCodec reads incoming requests from codec, calls the appropriate callback and writes +// the response back using the given codec. It will block until the codec is closed or the +// server is stopped. In either case the codec is closed. +// +// Note that codec options are no longer supported. +func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { + defer codec.Close() + + // Don't serve if server is stopped. + if atomic.LoadInt32(&s.run) == 0 { + return + } + + // Add the codec to the set so it can be closed by Stop. + s.codecs.Add(codec) + defer s.codecs.Remove(codec) + + c := initClient(codec, s.idgen, &s.services) + <-codec.Closed() + c.Close() +} + +// serveSingleRequest reads and processes a single RPC request from the given codec. This +// is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in +// this mode. +func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { + // Don't serve if server is stopped. + if atomic.LoadInt32(&s.run) == 0 { + return + } + + h := newHandler(ctx, codec, s.idgen, &s.services) + h.allowSubscribe = false + defer h.close(io.EOF, nil) + + reqs, batch, err := codec.Read() + if err != nil { + if err != io.EOF { + codec.Write(ctx, errorMessage(&invalidMessageError{"parse error"})) + } + return + } + if batch { + h.handleBatch(reqs) + } else { + h.handleMsg(reqs[0]) + } +} + +// Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending +// requests to finish, then closes all codecs which will cancel pending requests and +// subscriptions. +func (s *Server) Stop() { + if atomic.CompareAndSwapInt32(&s.run, 1, 0) { + log.Debug("RPC server shutting down") + s.codecs.Each(func(c interface{}) bool { + c.(ServerCodec).Close() + return true + }) + } +} + // RPCService gives meta information about the server. // e.g. gives information about the loaded modules. type RPCService struct { @@ -66,377 +136,12 @@ type RPCService struct { // Modules returns the list of RPC services with their version number func (s *RPCService) Modules() map[string]string { + s.server.services.mu.Lock() + defer s.server.services.mu.Unlock() + modules := make(map[string]string) - for name := range s.server.services { + for name := range s.server.services.services { modules[name] = "1.0" } return modules } - -// RegisterName will create a service for the given rcvr type under the given name. When no methods on the given rcvr -// match the criteria to be either a RPC method or a subscription an error is returned. Otherwise a new service is -// created and added to the service collection this server instance serves. -func (s *Server) RegisterName(name string, rcvr interface{}) error { - if s.services == nil { - s.services = make(serviceRegistry) - } - - svc := new(service) - svc.typ = reflect.TypeOf(rcvr) - rcvrVal := reflect.ValueOf(rcvr) - - if name == "" { - return fmt.Errorf("no service name for type %s", svc.typ.String()) - } - if !isExported(reflect.Indirect(rcvrVal).Type().Name()) { - return fmt.Errorf("%s is not exported", reflect.Indirect(rcvrVal).Type().Name()) - } - - methods, subscriptions := suitableCallbacks(rcvrVal, svc.typ) - - if len(methods) == 0 && len(subscriptions) == 0 { - return fmt.Errorf("Service %T doesn't have any suitable methods/subscriptions to expose", rcvr) - } - - // already a previous service register under given name, merge methods/subscriptions - if regsvc, present := s.services[name]; present { - for _, m := range methods { - regsvc.callbacks[formatName(m.method.Name)] = m - } - for _, s := range subscriptions { - regsvc.subscriptions[formatName(s.method.Name)] = s - } - return nil - } - - svc.name = name - svc.callbacks, svc.subscriptions = methods, subscriptions - - s.services[svc.name] = svc - return nil -} - -// serveRequest will reads requests from the codec, calls the RPC callback and -// writes the response to the given codec. -// -// If singleShot is true it will process a single request, otherwise it will handle -// requests until the codec returns an error when reading a request (in most cases -// an EOF). It executes requests in parallel when singleShot is false. -func (s *Server) serveRequest(ctx context.Context, codec ServerCodec, singleShot bool, options CodecOption) error { - var pend sync.WaitGroup - - defer func() { - if err := recover(); err != nil { - const size = 64 << 10 - buf := make([]byte, size) - buf = buf[:runtime.Stack(buf, false)] - log.Error(string(buf)) - } - s.codecsMu.Lock() - s.codecs.Remove(codec) - s.codecsMu.Unlock() - }() - - // ctx, cancel := context.WithCancel(context.Background()) - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - // if the codec supports notification include a notifier that callbacks can use - // to send notification to clients. It is tied to the codec/connection. If the - // connection is closed the notifier will stop and cancels all active subscriptions. - if options&OptionSubscriptions == OptionSubscriptions { - ctx = context.WithValue(ctx, notifierKey{}, newNotifier(codec)) - } - s.codecsMu.Lock() - if atomic.LoadInt32(&s.run) != 1 { // server stopped - s.codecsMu.Unlock() - return &shutdownError{} - } - s.codecs.Add(codec) - s.codecsMu.Unlock() - - // test if the server is ordered to stop - for atomic.LoadInt32(&s.run) == 1 { - reqs, batch, err := s.readRequest(codec) - if err != nil { - // If a parsing error occurred, send an error - if err.Error() != "EOF" { - log.Debug(fmt.Sprintf("read error %v\n", err)) - codec.Write(codec.CreateErrorResponse(nil, err)) - } - // Error or end of stream, wait for requests and tear down - pend.Wait() - return nil - } - - // check if server is ordered to shutdown and return an error - // telling the client that his request failed. - if atomic.LoadInt32(&s.run) != 1 { - err = &shutdownError{} - if batch { - resps := make([]interface{}, len(reqs)) - for i, r := range reqs { - resps[i] = codec.CreateErrorResponse(&r.id, err) - } - codec.Write(resps) - } else { - codec.Write(codec.CreateErrorResponse(&reqs[0].id, err)) - } - return nil - } - // If a single shot request is executing, run and return immediately - if singleShot { - if batch { - s.execBatch(ctx, codec, reqs) - } else { - s.exec(ctx, codec, reqs[0]) - } - return nil - } - // For multi-shot connections, start a goroutine to serve and loop back - pend.Add(1) - - go func(reqs []*serverRequest, batch bool) { - defer pend.Done() - if batch { - s.execBatch(ctx, codec, reqs) - } else { - s.exec(ctx, codec, reqs[0]) - } - }(reqs, batch) - } - return nil -} - -// ServeCodec reads incoming requests from codec, calls the appropriate callback and writes the -// response back using the given codec. It will block until the codec is closed or the server is -// stopped. In either case the codec is closed. -func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { - defer codec.Close() - s.serveRequest(context.Background(), codec, false, options) -} - -// ServeSingleRequest reads and processes a single RPC request from the given codec. It will not -// close the codec unless a non-recoverable error has occurred. Note, this method will return after -// a single request has been processed! -func (s *Server) ServeSingleRequest(ctx context.Context, codec ServerCodec, options CodecOption) { - s.serveRequest(ctx, codec, true, options) -} - -// Stop will stop reading new requests, wait for stopPendingRequestTimeout to allow pending requests to finish, -// close all codecs which will cancel pending requests/subscriptions. -func (s *Server) Stop() { - if atomic.CompareAndSwapInt32(&s.run, 1, 0) { - log.Debug("RPC Server shutdown initiatied") - s.codecsMu.Lock() - defer s.codecsMu.Unlock() - s.codecs.Each(func(c interface{}) bool { - c.(ServerCodec).Close() - return true - }) - } -} - -// createSubscription will call the subscription callback and returns the subscription id or error. -func (s *Server) createSubscription(ctx context.Context, c ServerCodec, req *serverRequest) (ID, error) { - // subscription have as first argument the context following optional arguments - args := []reflect.Value{req.callb.rcvr, reflect.ValueOf(ctx)} - args = append(args, req.args...) - reply := req.callb.method.Func.Call(args) - - if !reply[1].IsNil() { // subscription creation failed - return "", reply[1].Interface().(error) - } - - return reply[0].Interface().(*Subscription).ID, nil -} - -// handle executes a request and returns the response from the callback. -func (s *Server) handle(ctx context.Context, codec ServerCodec, req *serverRequest) (interface{}, func()) { - if req.err != nil { - return codec.CreateErrorResponse(&req.id, req.err), nil - } - - if req.isUnsubscribe { // cancel subscription, first param must be the subscription id - if len(req.args) >= 1 && req.args[0].Kind() == reflect.String { - notifier, supported := NotifierFromContext(ctx) - if !supported { // interface doesn't support subscriptions (e.g. http) - return codec.CreateErrorResponse(&req.id, &callbackError{ErrNotificationsUnsupported.Error()}), nil - } - - subid := ID(req.args[0].String()) - if err := notifier.unsubscribe(subid); err != nil { - return codec.CreateErrorResponse(&req.id, &callbackError{err.Error()}), nil - } - - return codec.CreateResponse(req.id, true), nil - } - return codec.CreateErrorResponse(&req.id, &invalidParamsError{"Expected subscription id as first argument"}), nil - } - - if req.callb.isSubscribe { - subid, err := s.createSubscription(ctx, codec, req) - if err != nil { - return codec.CreateErrorResponse(&req.id, &callbackError{err.Error()}), nil - } - - // active the subscription after the sub id was successfully sent to the client - activateSub := func() { - notifier, _ := NotifierFromContext(ctx) - notifier.activate(subid, req.svcname) - } - - return codec.CreateResponse(req.id, subid), activateSub - } - - // regular RPC call, prepare arguments - if len(req.args) != len(req.callb.argTypes) { - rpcErr := &invalidParamsError{fmt.Sprintf("%s%s%s expects %d parameters, got %d", - req.svcname, serviceMethodSeparator, req.callb.method.Name, - len(req.callb.argTypes), len(req.args))} - return codec.CreateErrorResponse(&req.id, rpcErr), nil - } - - arguments := []reflect.Value{req.callb.rcvr} - if req.callb.hasCtx { - arguments = append(arguments, reflect.ValueOf(ctx)) - } - if len(req.args) > 0 { - arguments = append(arguments, req.args...) - } - - // execute RPC method and return result - reply := req.callb.method.Func.Call(arguments) - if len(reply) == 0 { - return codec.CreateResponse(req.id, nil), nil - } - if req.callb.errPos >= 0 { // test if method returned an error - if !reply[req.callb.errPos].IsNil() { - e := reply[req.callb.errPos].Interface().(error) - res := codec.CreateErrorResponse(&req.id, &callbackError{e.Error()}) - return res, nil - } - } - return codec.CreateResponse(req.id, reply[0].Interface()), nil -} - -// exec executes the given request and writes the result back using the codec. -func (s *Server) exec(ctx context.Context, codec ServerCodec, req *serverRequest) { - var response interface{} - var callback func() - if req.err != nil { - response = codec.CreateErrorResponse(&req.id, req.err) - } else { - response, callback = s.handle(ctx, codec, req) - } - - if err := codec.Write(response); err != nil { - log.Error(fmt.Sprintf("%v\n", err)) - codec.Close() - } - - // when request was a subscribe request this allows these subscriptions to be actived - if callback != nil { - callback() - } -} - -// execBatch executes the given requests and writes the result back using the codec. -// It will only write the response back when the last request is processed. -func (s *Server) execBatch(ctx context.Context, codec ServerCodec, requests []*serverRequest) { - responses := make([]interface{}, len(requests)) - var callbacks []func() - for i, req := range requests { - if req.err != nil { - responses[i] = codec.CreateErrorResponse(&req.id, req.err) - } else { - var callback func() - if responses[i], callback = s.handle(ctx, codec, req); callback != nil { - callbacks = append(callbacks, callback) - } - } - } - - if err := codec.Write(responses); err != nil { - log.Error(fmt.Sprintf("%v\n", err)) - codec.Close() - } - - // when request holds one of more subscribe requests this allows these subscriptions to be activated - for _, c := range callbacks { - c() - } -} - -// readRequest requests the next (batch) request from the codec. It will return the collection -// of requests, an indication if the request was a batch, the invalid request identifier and an -// error when the request could not be read/parsed. -func (s *Server) readRequest(codec ServerCodec) ([]*serverRequest, bool, Error) { - reqs, batch, err := codec.ReadRequestHeaders() - if err != nil { - return nil, batch, err - } - - requests := make([]*serverRequest, len(reqs)) - - // verify requests - for i, r := range reqs { - var ok bool - var svc *service - - if r.err != nil { - requests[i] = &serverRequest{id: r.id, err: r.err} - continue - } - - if r.isPubSub && strings.HasSuffix(r.method, unsubscribeMethodSuffix) { - requests[i] = &serverRequest{id: r.id, isUnsubscribe: true} - argTypes := []reflect.Type{reflect.TypeOf("")} // expect subscription id as first arg - if args, err := codec.ParseRequestArguments(argTypes, r.params); err == nil { - requests[i].args = args - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - continue - } - - if svc, ok = s.services[r.service]; !ok { // rpc method isn't available - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} - continue - } - - if r.isPubSub { // eth_subscribe, r.method contains the subscription method name - if callb, ok := svc.subscriptions[r.method]; ok { - requests[i] = &serverRequest{id: r.id, svcname: svc.name, callb: callb} - if r.params != nil && len(callb.argTypes) > 0 { - argTypes := []reflect.Type{reflect.TypeOf("")} - argTypes = append(argTypes, callb.argTypes...) - if args, err := codec.ParseRequestArguments(argTypes, r.params); err == nil { - requests[i].args = args[1:] // first one is service.method name which isn't an actual argument - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - } - } else { - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} - } - continue - } - - if callb, ok := svc.callbacks[r.method]; ok { // lookup RPC method - requests[i] = &serverRequest{id: r.id, svcname: svc.name, callb: callb} - if r.params != nil && len(callb.argTypes) > 0 { - if args, err := codec.ParseRequestArguments(callb.argTypes, r.params); err == nil { - requests[i].args = args - } else { - requests[i].err = &invalidParamsError{err.Error()} - } - } - continue - } - - requests[i] = &serverRequest{id: r.id, err: &methodNotFoundError{r.service, r.method}} - } - - return requests, batch, nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/service.go b/vendor/github.com/ethereum/go-ethereum/rpc/service.go new file mode 100644 index 000000000..81e65f810 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rpc/service.go @@ -0,0 +1,285 @@ +// Copyright 2019 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 rpc + +import ( + "context" + "errors" + "fmt" + "reflect" + "runtime" + "strings" + "sync" + "unicode" + "unicode/utf8" + + "github.com/ethereum/go-ethereum/log" +) + +var ( + contextType = reflect.TypeOf((*context.Context)(nil)).Elem() + errorType = reflect.TypeOf((*error)(nil)).Elem() + subscriptionType = reflect.TypeOf(Subscription{}) + stringType = reflect.TypeOf("") +) + +type serviceRegistry struct { + mu sync.Mutex + services map[string]service +} + +// service represents a registered object. +type service struct { + name string // name for service + callbacks map[string]*callback // registered handlers + subscriptions map[string]*callback // available subscriptions/notifications +} + +// callback is a method callback which was registered in the server +type callback struct { + fn reflect.Value // the function + rcvr reflect.Value // receiver object of method, set if fn is method + argTypes []reflect.Type // input argument types + hasCtx bool // method's first argument is a context (not included in argTypes) + errPos int // err return idx, of -1 when method cannot return error + isSubscribe bool // true if this is a subscription callback +} + +func (r *serviceRegistry) registerName(name string, rcvr interface{}) error { + rcvrVal := reflect.ValueOf(rcvr) + if name == "" { + return fmt.Errorf("no service name for type %s", rcvrVal.Type().String()) + } + callbacks := suitableCallbacks(rcvrVal) + if len(callbacks) == 0 { + return fmt.Errorf("service %T doesn't have any suitable methods/subscriptions to expose", rcvr) + } + + r.mu.Lock() + defer r.mu.Unlock() + if r.services == nil { + r.services = make(map[string]service) + } + svc, ok := r.services[name] + if !ok { + svc = service{ + name: name, + callbacks: make(map[string]*callback), + subscriptions: make(map[string]*callback), + } + r.services[name] = svc + } + for name, cb := range callbacks { + if cb.isSubscribe { + svc.subscriptions[name] = cb + } else { + svc.callbacks[name] = cb + } + } + return nil +} + +// callback returns the callback corresponding to the given RPC method name. +func (r *serviceRegistry) callback(method string) *callback { + elem := strings.SplitN(method, serviceMethodSeparator, 2) + if len(elem) != 2 { + return nil + } + r.mu.Lock() + defer r.mu.Unlock() + return r.services[elem[0]].callbacks[elem[1]] +} + +// subscription returns a subscription callback in the given service. +func (r *serviceRegistry) subscription(service, name string) *callback { + r.mu.Lock() + defer r.mu.Unlock() + return r.services[service].subscriptions[name] +} + +// suitableCallbacks iterates over the methods of the given type. It determines if a method +// satisfies the criteria for a RPC callback or a subscription callback and adds it to the +// collection of callbacks. See server documentation for a summary of these criteria. +func suitableCallbacks(receiver reflect.Value) map[string]*callback { + typ := receiver.Type() + callbacks := make(map[string]*callback) + for m := 0; m < typ.NumMethod(); m++ { + method := typ.Method(m) + if method.PkgPath != "" { + continue // method not exported + } + cb := newCallback(receiver, method.Func) + if cb == nil { + continue // function invalid + } + name := formatName(method.Name) + callbacks[name] = cb + } + return callbacks +} + +// newCallback turns fn (a function) into a callback object. It returns nil if the function +// is unsuitable as an RPC callback. +func newCallback(receiver, fn reflect.Value) *callback { + fntype := fn.Type() + c := &callback{fn: fn, rcvr: receiver, errPos: -1, isSubscribe: isPubSub(fntype)} + // Determine parameter types. They must all be exported or builtin types. + c.makeArgTypes() + if !allExportedOrBuiltin(c.argTypes) { + return nil + } + // Verify return types. The function must return at most one error + // and/or one other non-error value. + outs := make([]reflect.Type, fntype.NumOut()) + for i := 0; i < fntype.NumOut(); i++ { + outs[i] = fntype.Out(i) + } + if len(outs) > 2 || !allExportedOrBuiltin(outs) { + return nil + } + // If an error is returned, it must be the last returned value. + switch { + case len(outs) == 1 && isErrorType(outs[0]): + c.errPos = 0 + case len(outs) == 2: + if isErrorType(outs[0]) || !isErrorType(outs[1]) { + return nil + } + c.errPos = 1 + } + return c +} + +// makeArgTypes composes the argTypes list. +func (c *callback) makeArgTypes() { + fntype := c.fn.Type() + // Skip receiver and context.Context parameter (if present). + firstArg := 0 + if c.rcvr.IsValid() { + firstArg++ + } + if fntype.NumIn() > firstArg && fntype.In(firstArg) == contextType { + c.hasCtx = true + firstArg++ + } + // Add all remaining parameters. + c.argTypes = make([]reflect.Type, fntype.NumIn()-firstArg) + for i := firstArg; i < fntype.NumIn(); i++ { + c.argTypes[i-firstArg] = fntype.In(i) + } +} + +// call invokes the callback. +func (c *callback) call(ctx context.Context, method string, args []reflect.Value) (res interface{}, errRes error) { + // Create the argument slice. + fullargs := make([]reflect.Value, 0, 2+len(args)) + if c.rcvr.IsValid() { + fullargs = append(fullargs, c.rcvr) + } + if c.hasCtx { + fullargs = append(fullargs, reflect.ValueOf(ctx)) + } + fullargs = append(fullargs, args...) + + // Catch panic while running the callback. + defer func() { + if err := recover(); err != nil { + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + log.Error("RPC method " + method + " crashed: " + fmt.Sprintf("%v\n%s", err, buf)) + errRes = errors.New("method handler crashed") + } + }() + // Run the callback. + results := c.fn.Call(fullargs) + if len(results) == 0 { + return nil, nil + } + if c.errPos >= 0 && !results[c.errPos].IsNil() { + // Method has returned non-nil error value. + err := results[c.errPos].Interface().(error) + return reflect.Value{}, err + } + return results[0].Interface(), nil +} + +// Is this an exported - upper case - name? +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +// Are all those types exported or built-in? +func allExportedOrBuiltin(types []reflect.Type) bool { + for _, typ := range types { + for typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + // PkgPath will be non-empty even for an exported type, + // so we need to check the type name as well. + if !isExported(typ.Name()) && typ.PkgPath() != "" { + return false + } + } + return true +} + +// Is t context.Context or *context.Context? +func isContextType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t == contextType +} + +// Does t satisfy the error interface? +func isErrorType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t.Implements(errorType) +} + +// Is t Subscription or *Subscription? +func isSubscriptionType(t reflect.Type) bool { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t == subscriptionType +} + +// isPubSub tests whether the given method has as as first argument a context.Context and +// returns the pair (Subscription, error). +func isPubSub(methodType reflect.Type) bool { + // numIn(0) is the receiver type + if methodType.NumIn() < 2 || methodType.NumOut() != 2 { + return false + } + return isContextType(methodType.In(1)) && + isSubscriptionType(methodType.Out(0)) && + isErrorType(methodType.Out(1)) +} + +// formatName converts to first character of name to lowercase. +func formatName(name string) string { + ret := []rune(name) + if len(ret) > 0 { + ret[0] = unicode.ToLower(ret[0]) + } + return string(ret) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go b/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go index ea552cca2..d5dc066c9 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/stdio.go @@ -19,6 +19,7 @@ package rpc import ( "context" "errors" + "io" "net" "os" "time" @@ -26,39 +27,38 @@ import ( // DialStdIO creates a client on stdin/stdout. func DialStdIO(ctx context.Context) (*Client, error) { - return newClient(ctx, func(_ context.Context) (net.Conn, error) { - return stdioConn{}, nil + return DialIO(ctx, os.Stdin, os.Stdout) +} + +// DialIO creates a client which uses the given IO channels +func DialIO(ctx context.Context, in io.Reader, out io.Writer) (*Client, error) { + return newClient(ctx, func(_ context.Context) (ServerCodec, error) { + return NewJSONCodec(stdioConn{ + in: in, + out: out, + }), nil }) } -type stdioConn struct{} +type stdioConn struct { + in io.Reader + out io.Writer +} func (io stdioConn) Read(b []byte) (n int, err error) { - return os.Stdin.Read(b) + return io.in.Read(b) } func (io stdioConn) Write(b []byte) (n int, err error) { - return os.Stdout.Write(b) + return io.out.Write(b) } func (io stdioConn) Close() error { return nil } -func (io stdioConn) LocalAddr() net.Addr { - return &net.UnixAddr{Name: "stdio", Net: "stdio"} -} - -func (io stdioConn) RemoteAddr() net.Addr { - return &net.UnixAddr{Name: "stdio", Net: "stdio"} -} - -func (io stdioConn) SetDeadline(t time.Time) error { - return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} -} - -func (io stdioConn) SetReadDeadline(t time.Time) error { - return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} +func (io stdioConn) RemoteAddr() string { + return "/dev/stdin" } func (io stdioConn) SetWriteDeadline(t time.Time) error { diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go b/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go index 6bbb6f75d..c1e869b8a 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/subscription.go @@ -17,9 +17,19 @@ package rpc import ( + "bufio" + "container/list" "context" + crand "crypto/rand" + "encoding/binary" + "encoding/hex" + "encoding/json" "errors" + "math/rand" + "reflect" + "strings" "sync" + "time" ) var ( @@ -29,10 +39,147 @@ var ( ErrSubscriptionNotFound = errors.New("subscription not found") ) +var globalGen = randomIDGenerator() + // ID defines a pseudo random number that is used to identify RPC subscriptions. type ID string -// a Subscription is created by a notifier and tight to that notifier. The client can use +// NewID returns a new, random ID. +func NewID() ID { + return globalGen() +} + +// randomIDGenerator returns a function generates a random IDs. +func randomIDGenerator() func() ID { + seed, err := binary.ReadVarint(bufio.NewReader(crand.Reader)) + if err != nil { + seed = int64(time.Now().Nanosecond()) + } + var ( + mu sync.Mutex + rng = rand.New(rand.NewSource(seed)) + ) + return func() ID { + mu.Lock() + defer mu.Unlock() + id := make([]byte, 16) + rng.Read(id) + return encodeID(id) + } +} + +func encodeID(b []byte) ID { + id := hex.EncodeToString(b) + id = strings.TrimLeft(id, "0") + if id == "" { + id = "0" // ID's are RPC quantities, no leading zero's and 0 is 0x0. + } + return ID("0x" + id) +} + +type notifierKey struct{} + +// NotifierFromContext returns the Notifier value stored in ctx, if any. +func NotifierFromContext(ctx context.Context) (*Notifier, bool) { + n, ok := ctx.Value(notifierKey{}).(*Notifier) + return n, ok +} + +// Notifier is tied to a RPC connection that supports subscriptions. +// Server callbacks use the notifier to send notifications. +type Notifier struct { + h *handler + namespace string + + mu sync.Mutex + sub *Subscription + buffer []json.RawMessage + callReturned bool + activated bool +} + +// CreateSubscription returns a new subscription that is coupled to the +// RPC connection. By default subscriptions are inactive and notifications +// are dropped until the subscription is marked as active. This is done +// by the RPC server after the subscription ID is send to the client. +func (n *Notifier) CreateSubscription() *Subscription { + n.mu.Lock() + defer n.mu.Unlock() + + if n.sub != nil { + panic("can't create multiple subscriptions with Notifier") + } else if n.callReturned { + panic("can't create subscription after subscribe call has returned") + } + n.sub = &Subscription{ID: n.h.idgen(), namespace: n.namespace, err: make(chan error, 1)} + return n.sub +} + +// Notify sends a notification to the client with the given data as payload. +// If an error occurs the RPC connection is closed and the error is returned. +func (n *Notifier) Notify(id ID, data interface{}) error { + enc, err := json.Marshal(data) + if err != nil { + return err + } + + n.mu.Lock() + defer n.mu.Unlock() + + if n.sub == nil { + panic("can't Notify before subscription is created") + } else if n.sub.ID != id { + panic("Notify with wrong ID") + } + if n.activated { + return n.send(n.sub, enc) + } + n.buffer = append(n.buffer, enc) + return nil +} + +// Closed returns a channel that is closed when the RPC connection is closed. +// Deprecated: use subscription error channel +func (n *Notifier) Closed() <-chan interface{} { + return n.h.conn.Closed() +} + +// takeSubscription returns the subscription (if one has been created). No subscription can +// be created after this call. +func (n *Notifier) takeSubscription() *Subscription { + n.mu.Lock() + defer n.mu.Unlock() + n.callReturned = true + return n.sub +} + +// acticate is called after the subscription ID was sent to client. Notifications are +// buffered before activation. This prevents notifications being sent to the client before +// the subscription ID is sent to the client. +func (n *Notifier) activate() error { + n.mu.Lock() + defer n.mu.Unlock() + + for _, data := range n.buffer { + if err := n.send(n.sub, data); err != nil { + return err + } + } + n.activated = true + return nil +} + +func (n *Notifier) send(sub *Subscription, data json.RawMessage) error { + params, _ := json.Marshal(&subscriptionResult{ID: string(sub.ID), Result: data}) + ctx := context.Background() + return n.h.conn.Write(ctx, &jsonrpcMessage{ + Version: vsn, + Method: n.namespace + notificationMethodSuffix, + Params: params, + }) +} + +// A Subscription is created by a notifier and tight to that notifier. The client can use // this subscription to wait for an unsubscribe request for the client, see Err(). type Subscription struct { ID ID @@ -45,105 +192,136 @@ func (s *Subscription) Err() <-chan error { return s.err } -// notifierKey is used to store a notifier within the connection context. -type notifierKey struct{} - -// Notifier is tight to a RPC connection that supports subscriptions. -// Server callbacks use the notifier to send notifications. -type Notifier struct { - codec ServerCodec - subMu sync.Mutex - active map[ID]*Subscription - inactive map[ID]*Subscription - buffer map[ID][]interface{} // unsent notifications of inactive subscriptions +// MarshalJSON marshals a subscription as its ID. +func (s *Subscription) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ID) } -// newNotifier creates a new notifier that can be used to send subscription -// notifications to the client. -func newNotifier(codec ServerCodec) *Notifier { - return &Notifier{ - codec: codec, - active: make(map[ID]*Subscription), - inactive: make(map[ID]*Subscription), - buffer: make(map[ID][]interface{}), +// ClientSubscription is a subscription established through the Client's Subscribe or +// EthSubscribe methods. +type ClientSubscription struct { + client *Client + etype reflect.Type + channel reflect.Value + namespace string + subid string + in chan json.RawMessage + + quitOnce sync.Once // ensures quit is closed once + quit chan struct{} // quit is closed when the subscription exits + errOnce sync.Once // ensures err is closed once + err chan error +} + +func newClientSubscription(c *Client, namespace string, channel reflect.Value) *ClientSubscription { + sub := &ClientSubscription{ + client: c, + namespace: namespace, + etype: channel.Type().Elem(), + channel: channel, + quit: make(chan struct{}), + err: make(chan error, 1), + in: make(chan json.RawMessage), } + return sub } -// NotifierFromContext returns the Notifier value stored in ctx, if any. -func NotifierFromContext(ctx context.Context) (*Notifier, bool) { - n, ok := ctx.Value(notifierKey{}).(*Notifier) - return n, ok +// Err returns the subscription error channel. The intended use of Err is to schedule +// resubscription when the client connection is closed unexpectedly. +// +// The error channel receives a value when the subscription has ended due +// to an error. The received error is nil if Close has been called +// on the underlying client and no other error has occurred. +// +// The error channel is closed when Unsubscribe is called on the subscription. +func (sub *ClientSubscription) Err() <-chan error { + return sub.err } -// CreateSubscription returns a new subscription that is coupled to the -// RPC connection. By default subscriptions are inactive and notifications -// are dropped until the subscription is marked as active. This is done -// by the RPC server after the subscription ID is send to the client. -func (n *Notifier) CreateSubscription() *Subscription { - s := &Subscription{ID: NewID(), err: make(chan error)} - n.subMu.Lock() - n.inactive[s.ID] = s - n.subMu.Unlock() - return s +// Unsubscribe unsubscribes the notification and closes the error channel. +// It can safely be called more than once. +func (sub *ClientSubscription) Unsubscribe() { + sub.quitWithError(nil, true) + sub.errOnce.Do(func() { close(sub.err) }) } -// Notify sends a notification to the client with the given data as payload. -// If an error occurs the RPC connection is closed and the error is returned. -func (n *Notifier) Notify(id ID, data interface{}) error { - n.subMu.Lock() - defer n.subMu.Unlock() - - if sub, active := n.active[id]; active { - n.send(sub, data) - } else { - n.buffer[id] = append(n.buffer[id], data) - } - return nil -} - -func (n *Notifier) send(sub *Subscription, data interface{}) error { - notification := n.codec.CreateNotification(string(sub.ID), sub.namespace, data) - err := n.codec.Write(notification) - if err != nil { - n.codec.Close() - } - return err -} - -// Closed returns a channel that is closed when the RPC connection is closed. -func (n *Notifier) Closed() <-chan interface{} { - return n.codec.Closed() -} - -// unsubscribe a subscription. -// If the subscription could not be found ErrSubscriptionNotFound is returned. -func (n *Notifier) unsubscribe(id ID) error { - n.subMu.Lock() - defer n.subMu.Unlock() - if s, found := n.active[id]; found { - close(s.err) - delete(n.active, id) - return nil - } - return ErrSubscriptionNotFound -} - -// activate enables a subscription. Until a subscription is enabled all -// notifications are dropped. This method is called by the RPC server after -// the subscription ID was sent to client. This prevents notifications being -// send to the client before the subscription ID is send to the client. -func (n *Notifier) activate(id ID, namespace string) { - n.subMu.Lock() - defer n.subMu.Unlock() - - if sub, found := n.inactive[id]; found { - sub.namespace = namespace - n.active[id] = sub - delete(n.inactive, id) - // Send buffered notifications. - for _, data := range n.buffer[id] { - n.send(sub, data) +func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) { + sub.quitOnce.Do(func() { + // The dispatch loop won't be able to execute the unsubscribe call + // if it is blocked on deliver. Close sub.quit first because it + // unblocks deliver. + close(sub.quit) + if unsubscribeServer { + sub.requestUnsubscribe() } - delete(n.buffer, id) + if err != nil { + if err == ErrClientQuit { + err = nil // Adhere to subscription semantics. + } + sub.err <- err + } + }) +} + +func (sub *ClientSubscription) deliver(result json.RawMessage) (ok bool) { + select { + case sub.in <- result: + return true + case <-sub.quit: + return false } } + +func (sub *ClientSubscription) start() { + sub.quitWithError(sub.forward()) +} + +func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) { + cases := []reflect.SelectCase{ + {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)}, + {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)}, + {Dir: reflect.SelectSend, Chan: sub.channel}, + } + buffer := list.New() + defer buffer.Init() + for { + var chosen int + var recv reflect.Value + if buffer.Len() == 0 { + // Idle, omit send case. + chosen, recv, _ = reflect.Select(cases[:2]) + } else { + // Non-empty buffer, send the first queued item. + cases[2].Send = reflect.ValueOf(buffer.Front().Value) + chosen, recv, _ = reflect.Select(cases) + } + + switch chosen { + case 0: // <-sub.quit + return nil, false + case 1: // <-sub.in + val, err := sub.unmarshal(recv.Interface().(json.RawMessage)) + if err != nil { + return err, true + } + if buffer.Len() == maxClientSubscriptionBuffer { + return ErrSubscriptionQueueOverflow, true + } + buffer.PushBack(val) + case 2: // sub.channel<- + cases[2].Send = reflect.Value{} // Don't hold onto the value. + buffer.Remove(buffer.Front()) + } + } +} + +func (sub *ClientSubscription) unmarshal(result json.RawMessage) (interface{}, error) { + val := reflect.New(sub.etype) + err := json.Unmarshal(result, val.Interface()) + return val.Elem().Interface(), err +} + +func (sub *ClientSubscription) requestUnsubscribe() error { + var result interface{} + return sub.client.Call(&result, sub.namespace+unsubscribeMethodSuffix, sub.subid) +} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/types.go b/vendor/github.com/ethereum/go-ethereum/rpc/types.go index 4252c3602..f31f09a77 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/types.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/types.go @@ -17,13 +17,11 @@ package rpc import ( + "context" "fmt" "math" - "reflect" "strings" - "sync" - mapset "github.com/deckarep/golang-set" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -35,57 +33,6 @@ type API struct { Public bool // indication if the methods must be considered safe for public use } -// callback is a method callback which was registered in the server -type callback struct { - rcvr reflect.Value // receiver of method - method reflect.Method // callback - argTypes []reflect.Type // input argument types - hasCtx bool // method's first argument is a context (not included in argTypes) - errPos int // err return idx, of -1 when method cannot return error - isSubscribe bool // indication if the callback is a subscription -} - -// service represents a registered object -type service struct { - name string // name for service - typ reflect.Type // receiver type - callbacks callbacks // registered handlers - subscriptions subscriptions // available subscriptions/notifications -} - -// serverRequest is an incoming request -type serverRequest struct { - id interface{} - svcname string - callb *callback - args []reflect.Value - isUnsubscribe bool - err Error -} - -type serviceRegistry map[string]*service // collection of services -type callbacks map[string]*callback // collection of RPC callbacks -type subscriptions map[string]*callback // collection of subscription callbacks - -// Server represents a RPC server -type Server struct { - services serviceRegistry - - run int32 - codecsMu sync.Mutex - codecs mapset.Set -} - -// rpcRequest represents a raw incoming RPC request -type rpcRequest struct { - service string - method string - id interface{} - isPubSub bool - params interface{} - err Error // invalid batch element -} - // Error wraps RPC errors, which contain an error code in addition to the message. type Error interface { Error() string // returns the message @@ -96,24 +43,19 @@ type Error interface { // a RPC session. Implementations must be go-routine safe since the codec can be called in // multiple go-routines concurrently. type ServerCodec interface { - // Read next request - ReadRequestHeaders() ([]rpcRequest, bool, Error) - // Parse request argument to the given types - ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) - // Assemble success response, expects response id and payload - CreateResponse(id interface{}, reply interface{}) interface{} - // Assemble error response, expects response id and error - CreateErrorResponse(id interface{}, err Error) interface{} - // Assemble error response with extra information about the error through info - CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} - // Create notification response - CreateNotification(id, namespace string, event interface{}) interface{} - // Write msg to client. - Write(msg interface{}) error - // Close underlying data stream + Read() (msgs []*jsonrpcMessage, isBatch bool, err error) Close() - // Closed when underlying connection is closed + jsonWriter +} + +// jsonWriter can write JSON messages to its underlying connection. +// Implementations must be safe for concurrent use. +type jsonWriter interface { + Write(context.Context, interface{}) error + // Closed returns a channel which is closed when the connection is closed. Closed() <-chan interface{} + // RemoteAddr returns the peer address of the connection. + RemoteAddr() string } type BlockNumber int64 diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/utils.go b/vendor/github.com/ethereum/go-ethereum/rpc/utils.go deleted file mode 100644 index 7f7ac4520..000000000 --- a/vendor/github.com/ethereum/go-ethereum/rpc/utils.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rpc - -import ( - "bufio" - "context" - crand "crypto/rand" - "encoding/binary" - "encoding/hex" - "math/rand" - "reflect" - "strings" - "sync" - "time" - "unicode" - "unicode/utf8" -) - -var ( - subscriptionIDGenMu sync.Mutex - subscriptionIDGen = idGenerator() -) - -// Is this an exported - upper case - name? -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// Is this type exported or a builtin? -func isExportedOrBuiltinType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - // PkgPath will be non-empty even for an exported type, - // so we need to check the type name as well. - return isExported(t.Name()) || t.PkgPath() == "" -} - -var contextType = reflect.TypeOf((*context.Context)(nil)).Elem() - -// isContextType returns an indication if the given t is of context.Context or *context.Context type -func isContextType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t == contextType -} - -var errorType = reflect.TypeOf((*error)(nil)).Elem() - -// Implements this type the error interface -func isErrorType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t.Implements(errorType) -} - -var subscriptionType = reflect.TypeOf((*Subscription)(nil)).Elem() - -// isSubscriptionType returns an indication if the given t is of Subscription or *Subscription type -func isSubscriptionType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - return t == subscriptionType -} - -// isPubSub tests whether the given method has as as first argument a context.Context -// and returns the pair (Subscription, error) -func isPubSub(methodType reflect.Type) bool { - // numIn(0) is the receiver type - if methodType.NumIn() < 2 || methodType.NumOut() != 2 { - return false - } - - return isContextType(methodType.In(1)) && - isSubscriptionType(methodType.Out(0)) && - isErrorType(methodType.Out(1)) -} - -// formatName will convert to first character to lower case -func formatName(name string) string { - ret := []rune(name) - if len(ret) > 0 { - ret[0] = unicode.ToLower(ret[0]) - } - return string(ret) -} - -// suitableCallbacks iterates over the methods of the given type. It will determine if a method satisfies the criteria -// for a RPC callback or a subscription callback and adds it to the collection of callbacks or subscriptions. See server -// documentation for a summary of these criteria. -func suitableCallbacks(rcvr reflect.Value, typ reflect.Type) (callbacks, subscriptions) { - callbacks := make(callbacks) - subscriptions := make(subscriptions) - -METHODS: - for m := 0; m < typ.NumMethod(); m++ { - method := typ.Method(m) - mtype := method.Type - mname := formatName(method.Name) - if method.PkgPath != "" { // method must be exported - continue - } - - var h callback - h.isSubscribe = isPubSub(mtype) - h.rcvr = rcvr - h.method = method - h.errPos = -1 - - firstArg := 1 - numIn := mtype.NumIn() - if numIn >= 2 && mtype.In(1) == contextType { - h.hasCtx = true - firstArg = 2 - } - - if h.isSubscribe { - h.argTypes = make([]reflect.Type, numIn-firstArg) // skip rcvr type - for i := firstArg; i < numIn; i++ { - argType := mtype.In(i) - if isExportedOrBuiltinType(argType) { - h.argTypes[i-firstArg] = argType - } else { - continue METHODS - } - } - - subscriptions[mname] = &h - continue METHODS - } - - // determine method arguments, ignore first arg since it's the receiver type - // Arguments must be exported or builtin types - h.argTypes = make([]reflect.Type, numIn-firstArg) - for i := firstArg; i < numIn; i++ { - argType := mtype.In(i) - if !isExportedOrBuiltinType(argType) { - continue METHODS - } - h.argTypes[i-firstArg] = argType - } - - // check that all returned values are exported or builtin types - for i := 0; i < mtype.NumOut(); i++ { - if !isExportedOrBuiltinType(mtype.Out(i)) { - continue METHODS - } - } - - // when a method returns an error it must be the last returned value - h.errPos = -1 - for i := 0; i < mtype.NumOut(); i++ { - if isErrorType(mtype.Out(i)) { - h.errPos = i - break - } - } - - if h.errPos >= 0 && h.errPos != mtype.NumOut()-1 { - continue METHODS - } - - switch mtype.NumOut() { - case 0, 1, 2: - if mtype.NumOut() == 2 && h.errPos == -1 { // method must one return value and 1 error - continue METHODS - } - callbacks[mname] = &h - } - } - - return callbacks, subscriptions -} - -// idGenerator helper utility that generates a (pseudo) random sequence of -// bytes that are used to generate identifiers. -func idGenerator() *rand.Rand { - if seed, err := binary.ReadVarint(bufio.NewReader(crand.Reader)); err == nil { - return rand.New(rand.NewSource(seed)) - } - return rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) -} - -// NewID generates a identifier that can be used as an identifier in the RPC interface. -// e.g. filter and subscription identifier. -func NewID() ID { - subscriptionIDGenMu.Lock() - defer subscriptionIDGenMu.Unlock() - - id := make([]byte, 16) - for i := 0; i < len(id); i += 7 { - val := subscriptionIDGen.Int63() - for j := 0; i+j < len(id) && j < 7; j++ { - id[i+j] = byte(val) - val >>= 8 - } - } - - rpcId := hex.EncodeToString(id) - // rpc ID's are RPC quantities, no leading zero's and 0 is 0x0 - rpcId = strings.TrimLeft(rpcId, "0") - if rpcId == "" { - rpcId = "0" - } - - return ID("0x" + rpcId) -} diff --git a/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go b/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go index eae8320e5..1632d6af4 100644 --- a/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go +++ b/vendor/github.com/ethereum/go-ethereum/rpc/websocket.go @@ -17,62 +17,26 @@ package rpc import ( - "bytes" "context" - "crypto/tls" "encoding/base64" - "encoding/json" "fmt" - "net" "net/http" "net/url" "os" "strings" - "time" + "sync" mapset "github.com/deckarep/golang-set" "github.com/ethereum/go-ethereum/log" - "golang.org/x/net/websocket" + "github.com/gorilla/websocket" ) -// websocketJSONCodec is a custom JSON codec with payload size enforcement and -// special number parsing. -var websocketJSONCodec = websocket.Codec{ - // Marshal is the stock JSON marshaller used by the websocket library too. - Marshal: func(v interface{}) ([]byte, byte, error) { - msg, err := json.Marshal(v) - return msg, websocket.TextFrame, err - }, - // Unmarshal is a specialized unmarshaller to properly convert numbers. - Unmarshal: func(msg []byte, payloadType byte, v interface{}) error { - dec := json.NewDecoder(bytes.NewReader(msg)) - dec.UseNumber() +const ( + wsReadBuffer = 1024 + wsWriteBuffer = 1024 +) - return dec.Decode(v) - }, -} - -// WebsocketHandler returns a handler that serves JSON-RPC to WebSocket connections. -// -// allowedOrigins should be a comma-separated list of allowed origin URLs. -// To allow connections with any origin, pass "*". -func (srv *Server) WebsocketHandler(allowedOrigins []string) http.Handler { - return websocket.Server{ - Handshake: wsHandshakeValidator(allowedOrigins), - Handler: func(conn *websocket.Conn) { - // Create a custom encode/decode pair to enforce payload size and number encoding - conn.MaxPayloadBytes = maxRequestContentLength - - encoder := func(v interface{}) error { - return websocketJSONCodec.Send(conn, v) - } - decoder := func(v interface{}) error { - return websocketJSONCodec.Receive(conn, v) - } - srv.ServeCodec(NewCodec(conn, encoder, decoder), OptionMethodInvocation|OptionSubscriptions) - }, - } -} +var wsBufferPool = new(sync.Pool) // NewWSServer creates a new websocket RPC server around an API provider. // @@ -81,10 +45,32 @@ func NewWSServer(allowedOrigins []string, srv *Server) *http.Server { return &http.Server{Handler: srv.WebsocketHandler(allowedOrigins)} } +// WebsocketHandler returns a handler that serves JSON-RPC to WebSocket connections. +// +// allowedOrigins should be a comma-separated list of allowed origin URLs. +// To allow connections with any origin, pass "*". +func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler { + var upgrader = websocket.Upgrader{ + ReadBufferSize: wsReadBuffer, + WriteBufferSize: wsWriteBuffer, + WriteBufferPool: wsBufferPool, + CheckOrigin: wsHandshakeValidator(allowedOrigins), + } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Debug("WebSocket upgrade failed", "err", err) + return + } + codec := newWebsocketCodec(conn) + s.ServeCodec(codec, OptionMethodInvocation|OptionSubscriptions) + }) +} + // wsHandshakeValidator returns a handler that verifies the origin during the // websocket upgrade process. When a '*' is specified as an allowed origins all // connections are accepted. -func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http.Request) error { +func wsHandshakeValidator(allowedOrigins []string) func(*http.Request) bool { origins := mapset.NewSet() allowAllOrigins := false @@ -96,7 +82,6 @@ func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http origins.Add(strings.ToLower(origin)) } } - // allow localhost if no allowedOrigins are specified. if len(origins.ToSlice()) == 0 { origins.Add("http://localhost") @@ -104,44 +89,39 @@ func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http origins.Add("http://" + strings.ToLower(hostname)) } } + log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v", origins.ToSlice())) - log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v\n", origins.ToSlice())) - - f := func(cfg *websocket.Config, req *http.Request) error { + f := func(req *http.Request) bool { + // Skip origin verification if no Origin header is present. The origin check + // is supposed to protect against browser based attacks. Browsers always set + // Origin. Non-browser software can put anything in origin and checking it doesn't + // provide additional security. + if _, ok := req.Header["Origin"]; !ok { + return true + } + // Verify origin against whitelist. origin := strings.ToLower(req.Header.Get("Origin")) if allowAllOrigins || origins.Contains(origin) { - return nil + return true } - log.Warn(fmt.Sprintf("origin '%s' not allowed on WS-RPC interface\n", origin)) - return fmt.Errorf("origin %s not allowed", origin) + log.Warn("Rejected WebSocket connection", "origin", origin) + return false } return f } -func wsGetConfig(endpoint, origin string) (*websocket.Config, error) { - if origin == "" { - var err error - if origin, err = os.Hostname(); err != nil { - return nil, err - } - if strings.HasPrefix(endpoint, "wss") { - origin = "https://" + strings.ToLower(origin) - } else { - origin = "http://" + strings.ToLower(origin) - } - } - config, err := websocket.NewConfig(endpoint, origin) - if err != nil { - return nil, err - } +type wsHandshakeError struct { + err error + status string +} - if config.Location.User != nil { - b64auth := base64.StdEncoding.EncodeToString([]byte(config.Location.User.String())) - config.Header.Add("Authorization", "Basic "+b64auth) - config.Location.User = nil +func (e wsHandshakeError) Error() string { + s := e.err.Error() + if e.status != "" { + s += " (HTTP status " + e.status + ")" } - return config, nil + return s } // DialWebsocket creates a new RPC client that communicates with a JSON-RPC server @@ -150,61 +130,46 @@ func wsGetConfig(endpoint, origin string) (*websocket.Config, error) { // The context is used for the initial connection establishment. It does not // affect subsequent interactions with the client. func DialWebsocket(ctx context.Context, endpoint, origin string) (*Client, error) { - config, err := wsGetConfig(endpoint, origin) + endpoint, header, err := wsClientHeaders(endpoint, origin) if err != nil { return nil, err } - - return newClient(ctx, func(ctx context.Context) (net.Conn, error) { - return wsDialContext(ctx, config) + dialer := websocket.Dialer{ + ReadBufferSize: wsReadBuffer, + WriteBufferSize: wsWriteBuffer, + WriteBufferPool: wsBufferPool, + } + return newClient(ctx, func(ctx context.Context) (ServerCodec, error) { + conn, resp, err := dialer.DialContext(ctx, endpoint, header) + if err != nil { + hErr := wsHandshakeError{err: err} + if resp != nil { + hErr.status = resp.Status + } + return nil, hErr + } + return newWebsocketCodec(conn), nil }) } -func wsDialContext(ctx context.Context, config *websocket.Config) (*websocket.Conn, error) { - var conn net.Conn - var err error - switch config.Location.Scheme { - case "ws": - conn, err = dialContext(ctx, "tcp", wsDialAddress(config.Location)) - case "wss": - dialer := contextDialer(ctx) - conn, err = tls.DialWithDialer(dialer, "tcp", wsDialAddress(config.Location), config.TlsConfig) - default: - err = websocket.ErrBadScheme - } +func wsClientHeaders(endpoint, origin string) (string, http.Header, error) { + endpointURL, err := url.Parse(endpoint) if err != nil { - return nil, err + return endpoint, nil, err } - ws, err := websocket.NewClient(config, conn) - if err != nil { - conn.Close() - return nil, err + header := make(http.Header) + if origin != "" { + header.Add("origin", origin) } - return ws, err + if endpointURL.User != nil { + b64auth := base64.StdEncoding.EncodeToString([]byte(endpointURL.User.String())) + header.Add("authorization", "Basic "+b64auth) + endpointURL.User = nil + } + return endpointURL.String(), header, nil } -var wsPortMap = map[string]string{"ws": "80", "wss": "443"} - -func wsDialAddress(location *url.URL) string { - if _, ok := wsPortMap[location.Scheme]; ok { - if _, _, err := net.SplitHostPort(location.Host); err != nil { - return net.JoinHostPort(location.Host, wsPortMap[location.Scheme]) - } - } - return location.Host -} - -func dialContext(ctx context.Context, network, addr string) (net.Conn, error) { - d := &net.Dialer{KeepAlive: tcpKeepAliveInterval} - return d.DialContext(ctx, network, addr) -} - -func contextDialer(ctx context.Context) *net.Dialer { - dialer := &net.Dialer{Cancel: ctx.Done(), KeepAlive: tcpKeepAliveInterval} - if deadline, ok := ctx.Deadline(); ok { - dialer.Deadline = deadline - } else { - dialer.Deadline = time.Now().Add(defaultDialTimeout) - } - return dialer +func newWebsocketCodec(conn *websocket.Conn) ServerCodec { + conn.SetReadLimit(maxRequestContentLength) + return newCodec(conn, conn.WriteJSON, conn.ReadJSON) } diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/api.go b/vendor/github.com/ethereum/go-ethereum/signer/core/api.go new file mode 100644 index 000000000..244767aca --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/api.go @@ -0,0 +1,568 @@ +// 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 core + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "os" + "reflect" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/accounts/scwallet" + "github.com/ethereum/go-ethereum/accounts/usbwallet" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/signer/storage" +) + +const ( + // numberOfAccountsToDerive For hardware wallets, the number of accounts to derive + numberOfAccountsToDerive = 10 + // ExternalAPIVersion -- see extapi_changelog.md + ExternalAPIVersion = "6.0.0" + // InternalAPIVersion -- see intapi_changelog.md + InternalAPIVersion = "7.0.0" +) + +// ExternalAPI defines the external API through which signing requests are made. +type ExternalAPI interface { + // List available accounts + List(ctx context.Context) ([]common.Address, error) + // New request to create a new account + New(ctx context.Context) (common.Address, error) + // SignTransaction request to sign the specified transaction + SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) + // SignData - request to sign the given data (plus prefix) + SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) + // SignTypedData - request to sign the given structured data (plus prefix) + SignTypedData(ctx context.Context, addr common.MixedcaseAddress, data TypedData) (hexutil.Bytes, error) + // EcRecover - recover public key from given message and signature + EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) + // Version info about the APIs + Version(ctx context.Context) (string, error) +} + +// UIClientAPI specifies what method a UI needs to implement to be able to be used as a +// UI for the signer +type UIClientAPI interface { + // ApproveTx prompt the user for confirmation to request to sign Transaction + ApproveTx(request *SignTxRequest) (SignTxResponse, error) + // ApproveSignData prompt the user for confirmation to request to sign data + ApproveSignData(request *SignDataRequest) (SignDataResponse, error) + // ApproveListing prompt the user for confirmation to list accounts + // the list of accounts to list can be modified by the UI + ApproveListing(request *ListRequest) (ListResponse, error) + // ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller + ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) + // ShowError displays error message to user + ShowError(message string) + // ShowInfo displays info message to user + ShowInfo(message string) + // OnApprovedTx notifies the UI about a transaction having been successfully signed. + // This method can be used by a UI to keep track of e.g. how much has been sent to a particular recipient. + OnApprovedTx(tx ethapi.SignTransactionResult) + // OnSignerStartup is invoked when the signer boots, and tells the UI info about external API location and version + // information + OnSignerStartup(info StartupInfo) + // OnInputRequired is invoked when clef requires user input, for example master password or + // pin-code for unlocking hardware wallets + OnInputRequired(info UserInputRequest) (UserInputResponse, error) + // RegisterUIServer tells the UI to use the given UIServerAPI for ui->clef communication + RegisterUIServer(api *UIServerAPI) +} + +// Validator defines the methods required to validate a transaction against some +// sanity defaults as well as any underlying 4byte method database. +// +// Use fourbyte.Database as an implementation. It is separated out of this package +// to allow pieces of the signer package to be used without having to load the +// 7MB embedded 4byte dump. +type Validator interface { + // ValidateTransaction does a number of checks on the supplied transaction, and + // returns either a list of warnings, or an error (indicating that the transaction + // should be immediately rejected). + ValidateTransaction(selector *string, tx *SendTxArgs) (*ValidationMessages, error) +} + +// SignerAPI defines the actual implementation of ExternalAPI +type SignerAPI struct { + chainID *big.Int + am *accounts.Manager + UI UIClientAPI + validator Validator + rejectMode bool + credentials storage.Storage +} + +// Metadata about a request +type Metadata struct { + Remote string `json:"remote"` + Local string `json:"local"` + Scheme string `json:"scheme"` + UserAgent string `json:"User-Agent"` + Origin string `json:"Origin"` +} + +func StartClefAccountManager(ksLocation string, nousb, lightKDF bool, scpath string) *accounts.Manager { + var ( + backends []accounts.Backend + n, p = keystore.StandardScryptN, keystore.StandardScryptP + ) + if lightKDF { + n, p = keystore.LightScryptN, keystore.LightScryptP + } + // support password based accounts + if len(ksLocation) > 0 { + backends = append(backends, keystore.NewKeyStore(ksLocation, n, p)) + } + if !nousb { + // Start a USB hub for Ledger hardware wallets + if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil { + log.Warn(fmt.Sprintf("Failed to start Ledger hub, disabling: %v", err)) + } else { + backends = append(backends, ledgerhub) + log.Debug("Ledger support enabled") + } + // Start a USB hub for Trezor hardware wallets (HID version) + if trezorhub, err := usbwallet.NewTrezorHubWithHID(); err != nil { + log.Warn(fmt.Sprintf("Failed to start HID Trezor hub, disabling: %v", err)) + } else { + backends = append(backends, trezorhub) + log.Debug("Trezor support enabled via HID") + } + // Start a USB hub for Trezor hardware wallets (WebUSB version) + if trezorhub, err := usbwallet.NewTrezorHubWithWebUSB(); err != nil { + log.Warn(fmt.Sprintf("Failed to start WebUSB Trezor hub, disabling: %v", err)) + } else { + backends = append(backends, trezorhub) + log.Debug("Trezor support enabled via WebUSB") + } + } + + // Start a smart card hub + if len(scpath) > 0 { + // Sanity check that the smartcard path is valid + fi, err := os.Stat(scpath) + if err != nil { + log.Info("Smartcard socket file missing, disabling", "err", err) + } else { + if fi.Mode()&os.ModeType != os.ModeSocket { + log.Error("Invalid smartcard socket file type", "path", scpath, "type", fi.Mode().String()) + } else { + if schub, err := scwallet.NewHub(scpath, scwallet.Scheme, ksLocation); err != nil { + log.Warn(fmt.Sprintf("Failed to start smart card hub, disabling: %v", err)) + } else { + backends = append(backends, schub) + } + } + } + } + + // Clef doesn't allow insecure http account unlock. + return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, backends...) +} + +// MetadataFromContext extracts Metadata from a given context.Context +func MetadataFromContext(ctx context.Context) Metadata { + m := Metadata{"NA", "NA", "NA", "", ""} // batman + + if v := ctx.Value("remote"); v != nil { + m.Remote = v.(string) + } + if v := ctx.Value("scheme"); v != nil { + m.Scheme = v.(string) + } + if v := ctx.Value("local"); v != nil { + m.Local = v.(string) + } + if v := ctx.Value("Origin"); v != nil { + m.Origin = v.(string) + } + if v := ctx.Value("User-Agent"); v != nil { + m.UserAgent = v.(string) + } + return m +} + +// String implements Stringer interface +func (m Metadata) String() string { + s, err := json.Marshal(m) + if err == nil { + return string(s) + } + return err.Error() +} + +// types for the requests/response types between signer and UI +type ( + // SignTxRequest contains info about a Transaction to sign + SignTxRequest struct { + Transaction SendTxArgs `json:"transaction"` + Callinfo []ValidationInfo `json:"call_info"` + Meta Metadata `json:"meta"` + } + // SignTxResponse result from SignTxRequest + SignTxResponse struct { + //The UI may make changes to the TX + Transaction SendTxArgs `json:"transaction"` + Approved bool `json:"approved"` + } + SignDataRequest struct { + ContentType string `json:"content_type"` + Address common.MixedcaseAddress `json:"address"` + Rawdata []byte `json:"raw_data"` + Messages []*NameValueType `json:"messages"` + Hash hexutil.Bytes `json:"hash"` + Meta Metadata `json:"meta"` + } + SignDataResponse struct { + Approved bool `json:"approved"` + } + NewAccountRequest struct { + Meta Metadata `json:"meta"` + } + NewAccountResponse struct { + Approved bool `json:"approved"` + } + ListRequest struct { + Accounts []accounts.Account `json:"accounts"` + Meta Metadata `json:"meta"` + } + ListResponse struct { + Accounts []accounts.Account `json:"accounts"` + } + Message struct { + Text string `json:"text"` + } + StartupInfo struct { + Info map[string]interface{} `json:"info"` + } + UserInputRequest struct { + Title string `json:"title"` + Prompt string `json:"prompt"` + IsPassword bool `json:"isPassword"` + } + UserInputResponse struct { + Text string `json:"text"` + } +) + +var ErrRequestDenied = errors.New("Request denied") + +// NewSignerAPI creates a new API that can be used for Account management. +// ksLocation specifies the directory where to store the password protected private +// key that is generated when a new Account is created. +// noUSB disables USB support that is required to support hardware devices such as +// ledger and trezor. +func NewSignerAPI(am *accounts.Manager, chainID int64, noUSB bool, ui UIClientAPI, validator Validator, advancedMode bool, credentials storage.Storage) *SignerAPI { + if advancedMode { + log.Info("Clef is in advanced mode: will warn instead of reject") + } + signer := &SignerAPI{big.NewInt(chainID), am, ui, validator, !advancedMode, credentials} + if !noUSB { + signer.startUSBListener() + } + return signer +} +func (api *SignerAPI) openTrezor(url accounts.URL) { + resp, err := api.UI.OnInputRequired(UserInputRequest{ + Prompt: "Pin required to open Trezor wallet\n" + + "Look at the device for number positions\n\n" + + "7 | 8 | 9\n" + + "--+---+--\n" + + "4 | 5 | 6\n" + + "--+---+--\n" + + "1 | 2 | 3\n\n", + IsPassword: true, + Title: "Trezor unlock", + }) + if err != nil { + log.Warn("failed getting trezor pin", "err", err) + return + } + // We're using the URL instead of the pointer to the + // Wallet -- perhaps it is not actually present anymore + w, err := api.am.Wallet(url.String()) + if err != nil { + log.Warn("wallet unavailable", "url", url) + return + } + err = w.Open(resp.Text) + if err != nil { + log.Warn("failed to open wallet", "wallet", url, "err", err) + return + } + +} + +// startUSBListener starts a listener for USB events, for hardware wallet interaction +func (api *SignerAPI) startUSBListener() { + events := make(chan accounts.WalletEvent, 16) + am := api.am + am.Subscribe(events) + go func() { + + // Open any wallets already attached + for _, wallet := range am.Wallets() { + if err := wallet.Open(""); err != nil { + log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) + if err == usbwallet.ErrTrezorPINNeeded { + go api.openTrezor(wallet.URL()) + } + } + } + // Listen for wallet event till termination + for event := range events { + switch event.Kind { + case accounts.WalletArrived: + if err := event.Wallet.Open(""); err != nil { + log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) + if err == usbwallet.ErrTrezorPINNeeded { + go api.openTrezor(event.Wallet.URL()) + } + } + case accounts.WalletOpened: + status, _ := event.Wallet.Status() + log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) + + // Derive first N accounts, hardcoded for now + var nextPath = make(accounts.DerivationPath, len(accounts.DefaultBaseDerivationPath)) + copy(nextPath[:], accounts.DefaultBaseDerivationPath[:]) + + for i := 0; i < numberOfAccountsToDerive; i++ { + acc, err := event.Wallet.Derive(nextPath, true) + if err != nil { + log.Warn("account derivation failed", "error", err) + } else { + log.Info("derived account", "address", acc.Address) + } + nextPath[len(nextPath)-1]++ + } + case accounts.WalletDropped: + log.Info("Old wallet dropped", "url", event.Wallet.URL()) + event.Wallet.Close() + } + } + }() +} + +// List returns the set of wallet this signer manages. Each wallet can contain +// multiple accounts. +func (api *SignerAPI) List(ctx context.Context) ([]common.Address, error) { + var accs []accounts.Account + for _, wallet := range api.am.Wallets() { + accs = append(accs, wallet.Accounts()...) + } + result, err := api.UI.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)}) + if err != nil { + return nil, err + } + if result.Accounts == nil { + return nil, ErrRequestDenied + + } + addresses := make([]common.Address, 0) + for _, acc := range result.Accounts { + addresses = append(addresses, acc.Address) + } + + return addresses, nil +} + +// New creates a new password protected Account. The private key is protected with +// the given password. Users are responsible to backup the private key that is stored +// in the keystore location thas was specified when this API was created. +func (api *SignerAPI) New(ctx context.Context) (common.Address, error) { + be := api.am.Backends(keystore.KeyStoreType) + if len(be) == 0 { + return common.Address{}, errors.New("password based accounts not supported") + } + if resp, err := api.UI.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)}); err != nil { + return common.Address{}, err + } else if !resp.Approved { + return common.Address{}, ErrRequestDenied + } + + // Three retries to get a valid password + for i := 0; i < 3; i++ { + resp, err := api.UI.OnInputRequired(UserInputRequest{ + "New account password", + fmt.Sprintf("Please enter a password for the new account to be created (attempt %d of 3)", i), + true}) + if err != nil { + log.Warn("error obtaining password", "attempt", i, "error", err) + continue + } + if pwErr := ValidatePasswordFormat(resp.Text); pwErr != nil { + api.UI.ShowError(fmt.Sprintf("Account creation attempt #%d failed due to password requirements: %v", (i + 1), pwErr)) + } else { + // No error + acc, err := be[0].(*keystore.KeyStore).NewAccount(resp.Text) + log.Info("Your new key was generated", "address", acc.Address) + log.Warn("Please backup your key file!", "path", acc.URL.Path) + log.Warn("Please remember your password!") + return acc.Address, err + } + } + // Otherwise fail, with generic error message + return common.Address{}, errors.New("account creation failed") +} + +// logDiff logs the difference between the incoming (original) transaction and the one returned from the signer. +// it also returns 'true' if the transaction was modified, to make it possible to configure the signer not to allow +// UI-modifications to requests +func logDiff(original *SignTxRequest, new *SignTxResponse) bool { + modified := false + if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) { + log.Info("Sender-account changed by UI", "was", f0, "is", f1) + modified = true + } + if t0, t1 := original.Transaction.To, new.Transaction.To; !reflect.DeepEqual(t0, t1) { + log.Info("Recipient-account changed by UI", "was", t0, "is", t1) + modified = true + } + if g0, g1 := original.Transaction.Gas, new.Transaction.Gas; g0 != g1 { + modified = true + log.Info("Gas changed by UI", "was", g0, "is", g1) + } + if g0, g1 := big.Int(original.Transaction.GasPrice), big.Int(new.Transaction.GasPrice); g0.Cmp(&g1) != 0 { + modified = true + log.Info("GasPrice changed by UI", "was", g0, "is", g1) + } + if v0, v1 := big.Int(original.Transaction.Value), big.Int(new.Transaction.Value); v0.Cmp(&v1) != 0 { + modified = true + log.Info("Value changed by UI", "was", v0, "is", v1) + } + if d0, d1 := original.Transaction.Data, new.Transaction.Data; d0 != d1 { + d0s := "" + d1s := "" + if d0 != nil { + d0s = hexutil.Encode(*d0) + } + if d1 != nil { + d1s = hexutil.Encode(*d1) + } + if d1s != d0s { + modified = true + log.Info("Data changed by UI", "was", d0s, "is", d1s) + } + } + if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 { + modified = true + log.Info("Nonce changed by UI", "was", n0, "is", n1) + } + return modified +} + +func (api *SignerAPI) lookupPassword(address common.Address) (string, error) { + return api.credentials.Get(address.Hex()) +} + +func (api *SignerAPI) lookupOrQueryPassword(address common.Address, title, prompt string) (string, error) { + // Look up the password and return if available + if pw, err := api.lookupPassword(address); err == nil { + return pw, nil + } + // Password unavailable, request it from the user + pwResp, err := api.UI.OnInputRequired(UserInputRequest{title, prompt, true}) + if err != nil { + log.Warn("error obtaining password", "error", err) + // We'll not forward the error here, in case the error contains info about the response from the UI, + // which could leak the password if it was malformed json or something + return "", errors.New("internal error") + } + return pwResp.Text, nil +} + +// SignTransaction signs the given Transaction and returns it both as json and rlp-encoded form +func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) { + var ( + err error + result SignTxResponse + ) + msgs, err := api.validator.ValidateTransaction(methodSelector, &args) + if err != nil { + return nil, err + } + // If we are in 'rejectMode', then reject rather than show the user warnings + if api.rejectMode { + if err := msgs.getWarnings(); err != nil { + return nil, err + } + } + req := SignTxRequest{ + Transaction: args, + Meta: MetadataFromContext(ctx), + Callinfo: msgs.Messages, + } + // Process approval + result, err = api.UI.ApproveTx(&req) + if err != nil { + return nil, err + } + if !result.Approved { + return nil, ErrRequestDenied + } + // Log changes made by the UI to the signing-request + logDiff(&req, &result) + var ( + acc accounts.Account + wallet accounts.Wallet + ) + acc = accounts.Account{Address: result.Transaction.From.Address()} + wallet, err = api.am.Find(acc) + if err != nil { + return nil, err + } + // Convert fields into a real transaction + var unsignedTx = result.Transaction.toTransaction() + // Get the password for the transaction + pw, err := api.lookupOrQueryPassword(acc.Address, "Account password", + fmt.Sprintf("Please enter the password for account %s", acc.Address.String())) + if err != nil { + return nil, err + } + // The one to sign is the one that was returned from the UI + signedTx, err := wallet.SignTxWithPassphrase(acc, pw, unsignedTx, api.chainID) + if err != nil { + api.UI.ShowError(err.Error()) + return nil, err + } + + rlpdata, err := rlp.EncodeToBytes(signedTx) + response := ethapi.SignTransactionResult{Raw: rlpdata, Tx: signedTx} + + // Finally, send the signed tx to the UI + api.UI.OnApprovedTx(response) + // ...and to the external caller + return &response, nil + +} + +// Returns the external api version. This method does not require user acceptance. Available methods are +// available via enumeration anyway, and this info does not contain user-specific data +func (api *SignerAPI) Version(ctx context.Context) (string, error) { + return ExternalAPIVersion, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/auditlog.go b/vendor/github.com/ethereum/go-ethereum/signer/core/auditlog.go new file mode 100644 index 000000000..1092e7a92 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/auditlog.go @@ -0,0 +1,104 @@ +// 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 core + +import ( + "context" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" +) + +type AuditLogger struct { + log log.Logger + api ExternalAPI +} + +func (l *AuditLogger) List(ctx context.Context) ([]common.Address, error) { + l.log.Info("List", "type", "request", "metadata", MetadataFromContext(ctx).String()) + res, e := l.api.List(ctx) + l.log.Info("List", "type", "response", "data", res) + + return res, e +} + +func (l *AuditLogger) New(ctx context.Context) (common.Address, error) { + return l.api.New(ctx) +} + +func (l *AuditLogger) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) { + sel := "" + if methodSelector != nil { + sel = *methodSelector + } + l.log.Info("SignTransaction", "type", "request", "metadata", MetadataFromContext(ctx).String(), + "tx", args.String(), + "methodSelector", sel) + + res, e := l.api.SignTransaction(ctx, args, methodSelector) + if res != nil { + l.log.Info("SignTransaction", "type", "response", "data", common.Bytes2Hex(res.Raw), "error", e) + } else { + l.log.Info("SignTransaction", "type", "response", "data", res, "error", e) + } + return res, e +} + +func (l *AuditLogger) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) { + l.log.Info("SignData", "type", "request", "metadata", MetadataFromContext(ctx).String(), + "addr", addr.String(), "data", data, "content-type", contentType) + b, e := l.api.SignData(ctx, contentType, addr, data) + l.log.Info("SignData", "type", "response", "data", common.Bytes2Hex(b), "error", e) + return b, e +} + +func (l *AuditLogger) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, data TypedData) (hexutil.Bytes, error) { + l.log.Info("SignTypedData", "type", "request", "metadata", MetadataFromContext(ctx).String(), + "addr", addr.String(), "data", data) + b, e := l.api.SignTypedData(ctx, addr, data) + l.log.Info("SignTypedData", "type", "response", "data", common.Bytes2Hex(b), "error", e) + return b, e +} + +func (l *AuditLogger) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { + l.log.Info("EcRecover", "type", "request", "metadata", MetadataFromContext(ctx).String(), + "data", common.Bytes2Hex(data), "sig", common.Bytes2Hex(sig)) + b, e := l.api.EcRecover(ctx, data, sig) + l.log.Info("EcRecover", "type", "response", "address", b.String(), "error", e) + return b, e +} + +func (l *AuditLogger) Version(ctx context.Context) (string, error) { + l.log.Info("Version", "type", "request", "metadata", MetadataFromContext(ctx).String()) + data, err := l.api.Version(ctx) + l.log.Info("Version", "type", "response", "data", data, "error", err) + return data, err + +} + +func NewAuditLogger(path string, api ExternalAPI) (*AuditLogger, error) { + l := log.New("api", "signer") + handler, err := log.FileHandler(path, log.LogfmtFormat()) + if err != nil { + return nil, err + } + l.SetHandler(handler) + l.Info("Configured", "audit log", path) + return &AuditLogger{l, api}, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/cliui.go b/vendor/github.com/ethereum/go-ethereum/signer/core/cliui.go new file mode 100644 index 000000000..1502238bf --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/cliui.go @@ -0,0 +1,250 @@ +// 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 core + +import ( + "bufio" + "encoding/json" + "fmt" + "os" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "golang.org/x/crypto/ssh/terminal" +) + +type CommandlineUI struct { + in *bufio.Reader + mu sync.Mutex +} + +func NewCommandlineUI() *CommandlineUI { + return &CommandlineUI{in: bufio.NewReader(os.Stdin)} +} + +func (ui *CommandlineUI) RegisterUIServer(api *UIServerAPI) { + // noop +} + +// readString reads a single line from stdin, trimming if from spaces, enforcing +// non-emptyness. +func (ui *CommandlineUI) readString() string { + for { + fmt.Printf("> ") + text, err := ui.in.ReadString('\n') + if err != nil { + log.Crit("Failed to read user input", "err", err) + } + if text = strings.TrimSpace(text); text != "" { + return text + } + } +} + +// readPassword reads a single line from stdin, trimming it from the trailing new +// line and returns it. The input will not be echoed. +func (ui *CommandlineUI) readPassword() string { + fmt.Printf("Enter password to approve:\n") + fmt.Printf("> ") + + text, err := terminal.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + log.Crit("Failed to read password", "err", err) + } + fmt.Println() + fmt.Println("-----------------------") + return string(text) +} + +// readPassword reads a single line from stdin, trimming it from the trailing new +// line and returns it. The input will not be echoed. +func (ui *CommandlineUI) readPasswordText(inputstring string) string { + fmt.Printf("Enter %s:\n", inputstring) + fmt.Printf("> ") + text, err := terminal.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + log.Crit("Failed to read password", "err", err) + } + fmt.Println("-----------------------") + return string(text) +} + +func (ui *CommandlineUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) { + + fmt.Printf("## %s\n\n%s\n", info.Title, info.Prompt) + if info.IsPassword { + fmt.Printf("> ") + text, err := terminal.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + log.Error("Failed to read password", "err", err) + } + fmt.Println("-----------------------") + return UserInputResponse{string(text)}, err + } + text := ui.readString() + fmt.Println("-----------------------") + return UserInputResponse{text}, nil +} + +// confirm returns true if user enters 'Yes', otherwise false +func (ui *CommandlineUI) confirm() bool { + fmt.Printf("Approve? [y/N]:\n") + if ui.readString() == "y" { + return true + } + fmt.Println("-----------------------") + return false +} + +func showMetadata(metadata Metadata) { + fmt.Printf("Request context:\n\t%v -> %v -> %v\n", metadata.Remote, metadata.Scheme, metadata.Local) + fmt.Printf("\nAdditional HTTP header data, provided by the external caller:\n") + fmt.Printf("\tUser-Agent: %v\n\tOrigin: %v\n", metadata.UserAgent, metadata.Origin) +} + +// ApproveTx prompt the user for confirmation to request to sign Transaction +func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) { + ui.mu.Lock() + defer ui.mu.Unlock() + weival := request.Transaction.Value.ToInt() + fmt.Printf("--------- Transaction request-------------\n") + if to := request.Transaction.To; to != nil { + fmt.Printf("to: %v\n", to.Original()) + if !to.ValidChecksum() { + fmt.Printf("\nWARNING: Invalid checksum on to-address!\n\n") + } + } else { + fmt.Printf("to: \n") + } + fmt.Printf("from: %v\n", request.Transaction.From.String()) + fmt.Printf("value: %v wei\n", weival) + fmt.Printf("gas: %v (%v)\n", request.Transaction.Gas, uint64(request.Transaction.Gas)) + fmt.Printf("gasprice: %v wei\n", request.Transaction.GasPrice.ToInt()) + fmt.Printf("nonce: %v (%v)\n", request.Transaction.Nonce, uint64(request.Transaction.Nonce)) + if request.Transaction.Data != nil { + d := *request.Transaction.Data + if len(d) > 0 { + + fmt.Printf("data: %v\n", hexutil.Encode(d)) + } + } + if request.Callinfo != nil { + fmt.Printf("\nTransaction validation:\n") + for _, m := range request.Callinfo { + fmt.Printf(" * %s : %s\n", m.Typ, m.Message) + } + fmt.Println() + + } + fmt.Printf("\n") + showMetadata(request.Meta) + fmt.Printf("-------------------------------------------\n") + if !ui.confirm() { + return SignTxResponse{request.Transaction, false}, nil + } + return SignTxResponse{request.Transaction, true}, nil +} + +// ApproveSignData prompt the user for confirmation to request to sign data +func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest) (SignDataResponse, error) { + ui.mu.Lock() + defer ui.mu.Unlock() + + fmt.Printf("-------- Sign data request--------------\n") + fmt.Printf("Account: %s\n", request.Address.String()) + fmt.Printf("messages:\n") + for _, nvt := range request.Messages { + fmt.Printf("\u00a0\u00a0%v\n", strings.TrimSpace(nvt.Pprint(1))) + } + fmt.Printf("raw data: \n%q\n", request.Rawdata) + fmt.Printf("data hash: %v\n", request.Hash) + fmt.Printf("-------------------------------------------\n") + showMetadata(request.Meta) + if !ui.confirm() { + return SignDataResponse{false}, nil + } + return SignDataResponse{true}, nil +} + +// ApproveListing prompt the user for confirmation to list accounts +// the list of accounts to list can be modified by the UI +func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) { + ui.mu.Lock() + defer ui.mu.Unlock() + + fmt.Printf("-------- List Account request--------------\n") + fmt.Printf("A request has been made to list all accounts. \n") + fmt.Printf("You can select which accounts the caller can see\n") + for _, account := range request.Accounts { + fmt.Printf(" [x] %v\n", account.Address.Hex()) + fmt.Printf(" URL: %v\n", account.URL) + } + fmt.Printf("-------------------------------------------\n") + showMetadata(request.Meta) + if !ui.confirm() { + return ListResponse{nil}, nil + } + return ListResponse{request.Accounts}, nil +} + +// ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller +func (ui *CommandlineUI) ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) { + + ui.mu.Lock() + defer ui.mu.Unlock() + + fmt.Printf("-------- New Account request--------------\n\n") + fmt.Printf("A request has been made to create a new account. \n") + fmt.Printf("Approving this operation means that a new account is created,\n") + fmt.Printf("and the address is returned to the external caller\n\n") + showMetadata(request.Meta) + if !ui.confirm() { + return NewAccountResponse{false}, nil + } + return NewAccountResponse{true}, nil +} + +// ShowError displays error message to user +func (ui *CommandlineUI) ShowError(message string) { + fmt.Printf("## Error \n%s\n", message) + fmt.Printf("-------------------------------------------\n") +} + +// ShowInfo displays info message to user +func (ui *CommandlineUI) ShowInfo(message string) { + fmt.Printf("## Info \n%s\n", message) +} + +func (ui *CommandlineUI) OnApprovedTx(tx ethapi.SignTransactionResult) { + fmt.Printf("Transaction signed:\n ") + if jsn, err := json.MarshalIndent(tx.Tx, " ", " "); err != nil { + fmt.Printf("WARN: marshalling error %v\n", err) + } else { + fmt.Println(string(jsn)) + } +} + +func (ui *CommandlineUI) OnSignerStartup(info StartupInfo) { + + fmt.Printf("------- Signer info -------\n") + for k, v := range info.Info { + fmt.Printf("* %v : %v\n", k, v) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/signed_data.go b/vendor/github.com/ethereum/go-ethereum/signer/core/signed_data.go new file mode 100644 index 000000000..f512be7ce --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/signed_data.go @@ -0,0 +1,1002 @@ +// Copyright 2019 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 core + +import ( + "bytes" + "context" + "errors" + "fmt" + "math/big" + "mime" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "unicode" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/clique" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" +) + +type SigFormat struct { + Mime string + ByteVersion byte +} + +var ( + IntendedValidator = SigFormat{ + accounts.MimetypeDataWithValidator, + 0x00, + } + DataTyped = SigFormat{ + accounts.MimetypeTypedData, + 0x01, + } + ApplicationClique = SigFormat{ + accounts.MimetypeClique, + 0x02, + } + TextPlain = SigFormat{ + accounts.MimetypeTextPlain, + 0x45, + } +) + +type ValidatorData struct { + Address common.Address + Message hexutil.Bytes +} + +type TypedData struct { + Types Types `json:"types"` + PrimaryType string `json:"primaryType"` + Domain TypedDataDomain `json:"domain"` + Message TypedDataMessage `json:"message"` +} + +type Type struct { + Name string `json:"name"` + Type string `json:"type"` +} + +func (t *Type) isArray() bool { + return strings.HasSuffix(t.Type, "[]") +} + +// typeName returns the canonical name of the type. If the type is 'Person[]', then +// this method returns 'Person' +func (t *Type) typeName() string { + if strings.HasSuffix(t.Type, "[]") { + return strings.TrimSuffix(t.Type, "[]") + } + return t.Type +} + +func (t *Type) isReferenceType() bool { + if len(t.Type) == 0 { + return false + } + // Reference types must have a leading uppercase characer + return unicode.IsUpper([]rune(t.Type)[0]) +} + +type Types map[string][]Type + +type TypePriority struct { + Type string + Value uint +} + +type TypedDataMessage = map[string]interface{} + +type TypedDataDomain struct { + Name string `json:"name"` + Version string `json:"version"` + ChainId *math.HexOrDecimal256 `json:"chainId"` + VerifyingContract string `json:"verifyingContract"` + Salt string `json:"salt"` +} + +var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Z](\w*)(\[\])?$`) + +// sign receives a request and produces a signature +// +// Note, the produced signature conforms to the secp256k1 curve R, S and V values, +// where the V value will be 27 or 28 for legacy reasons, if legacyV==true. +func (api *SignerAPI) sign(addr common.MixedcaseAddress, req *SignDataRequest, legacyV bool) (hexutil.Bytes, error) { + // We make the request prior to looking up if we actually have the account, to prevent + // account-enumeration via the API + res, err := api.UI.ApproveSignData(req) + if err != nil { + return nil, err + } + if !res.Approved { + return nil, ErrRequestDenied + } + // Look up the wallet containing the requested signer + account := accounts.Account{Address: addr.Address()} + wallet, err := api.am.Find(account) + if err != nil { + return nil, err + } + pw, err := api.lookupOrQueryPassword(account.Address, + "Password for signing", + fmt.Sprintf("Please enter password for signing data with account %s", account.Address.Hex())) + if err != nil { + return nil, err + } + // Sign the data with the wallet + signature, err := wallet.SignDataWithPassphrase(account, pw, req.ContentType, req.Rawdata) + if err != nil { + return nil, err + } + if legacyV { + signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper + } + return signature, nil +} + +// SignData signs the hash of the provided data, but does so differently +// depending on the content-type specified. +// +// Different types of validation occur. +func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) { + var req, transformV, err = api.determineSignatureFormat(ctx, contentType, addr, data) + if err != nil { + return nil, err + } + signature, err := api.sign(addr, req, transformV) + if err != nil { + api.UI.ShowError(err.Error()) + return nil, err + } + return signature, nil +} + +// determineSignatureFormat determines which signature method should be used based upon the mime type +// In the cases where it matters ensure that the charset is handled. The charset +// resides in the 'params' returned as the second returnvalue from mime.ParseMediaType +// charset, ok := params["charset"] +// As it is now, we accept any charset and just treat it as 'raw'. +// This method returns the mimetype for signing along with the request +func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (*SignDataRequest, bool, error) { + var ( + req *SignDataRequest + useEthereumV = true // Default to use V = 27 or 28, the legacy Ethereum format + ) + mediaType, _, err := mime.ParseMediaType(contentType) + if err != nil { + return nil, useEthereumV, err + } + + switch mediaType { + case IntendedValidator.Mime: + // Data with an intended validator + validatorData, err := UnmarshalValidatorData(data) + if err != nil { + return nil, useEthereumV, err + } + sighash, msg := SignTextValidator(validatorData) + messages := []*NameValueType{ + { + Name: "This is a request to sign data intended for a particular validator (see EIP 191 version 0)", + Typ: "description", + Value: "", + }, + { + Name: "Intended validator address", + Typ: "address", + Value: validatorData.Address.String(), + }, + { + Name: "Application-specific data", + Typ: "hexdata", + Value: validatorData.Message, + }, + { + Name: "Full message for signing", + Typ: "hexdata", + Value: fmt.Sprintf("0x%x", msg), + }, + } + req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Messages: messages, Hash: sighash} + case ApplicationClique.Mime: + // Clique is the Ethereum PoA standard + stringData, ok := data.(string) + if !ok { + return nil, useEthereumV, fmt.Errorf("input for %v must be an hex-encoded string", ApplicationClique.Mime) + } + cliqueData, err := hexutil.Decode(stringData) + if err != nil { + return nil, useEthereumV, err + } + header := &types.Header{} + if err := rlp.DecodeBytes(cliqueData, header); err != nil { + return nil, useEthereumV, err + } + // The incoming clique header is already truncated, sent to us with a extradata already shortened + if len(header.Extra) < 65 { + // Need to add it back, to get a suitable length for hashing + newExtra := make([]byte, len(header.Extra)+65) + copy(newExtra, header.Extra) + header.Extra = newExtra + } + // Get back the rlp data, encoded by us + sighash, cliqueRlp, err := cliqueHeaderHashAndRlp(header) + if err != nil { + return nil, useEthereumV, err + } + messages := []*NameValueType{ + { + Name: "Clique header", + Typ: "clique", + Value: fmt.Sprintf("clique header %d [0x%x]", header.Number, header.Hash()), + }, + } + // Clique uses V on the form 0 or 1 + useEthereumV = false + req = &SignDataRequest{ContentType: mediaType, Rawdata: cliqueRlp, Messages: messages, Hash: sighash} + default: // also case TextPlain.Mime: + // Calculates an Ethereum ECDSA signature for: + // hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}") + // We expect it to be a string + if stringData, ok := data.(string); !ok { + return nil, useEthereumV, fmt.Errorf("input for text/plain must be an hex-encoded string") + } else { + if textData, err := hexutil.Decode(stringData); err != nil { + return nil, useEthereumV, err + } else { + sighash, msg := accounts.TextAndHash(textData) + messages := []*NameValueType{ + { + Name: "message", + Typ: accounts.MimetypeTextPlain, + Value: msg, + }, + } + req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Messages: messages, Hash: sighash} + } + } + } + req.Address = addr + req.Meta = MetadataFromContext(ctx) + return req, useEthereumV, nil +} + +// SignTextWithValidator signs the given message which can be further recovered +// with the given validator. +// hash = keccak256("\x19\x00"${address}${data}). +func SignTextValidator(validatorData ValidatorData) (hexutil.Bytes, string) { + msg := fmt.Sprintf("\x19\x00%s%s", string(validatorData.Address.Bytes()), string(validatorData.Message)) + return crypto.Keccak256([]byte(msg)), msg +} + +// cliqueHeaderHashAndRlp returns the hash which is used as input for the proof-of-authority +// signing. It is the hash of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// The method requires the extra data to be at least 65 bytes -- the original implementation +// in clique.go panics if this is the case, thus it's been reimplemented here to avoid the panic +// and simply return an error instead +func cliqueHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error) { + if len(header.Extra) < 65 { + err = fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra)) + return + } + rlp = clique.CliqueRLP(header) + hash = clique.SealHash(header).Bytes() + return hash, rlp, err +} + +// SignTypedData signs EIP-712 conformant typed data +// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}") +func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) { + domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) + if err != nil { + return nil, err + } + typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) + if err != nil { + return nil, err + } + rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))) + sighash := crypto.Keccak256(rawData) + messages, err := typedData.Format() + if err != nil { + return nil, err + } + req := &SignDataRequest{ContentType: DataTyped.Mime, Rawdata: rawData, Messages: messages, Hash: sighash} + signature, err := api.sign(addr, req, true) + if err != nil { + api.UI.ShowError(err.Error()) + return nil, err + } + return signature, nil +} + +// HashStruct generates a keccak256 hash of the encoding of the provided data +func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage) (hexutil.Bytes, error) { + encodedData, err := typedData.EncodeData(primaryType, data, 1) + if err != nil { + return nil, err + } + return crypto.Keccak256(encodedData), nil +} + +// Dependencies returns an array of custom types ordered by their hierarchical reference tree +func (typedData *TypedData) Dependencies(primaryType string, found []string) []string { + includes := func(arr []string, str string) bool { + for _, obj := range arr { + if obj == str { + return true + } + } + return false + } + + if includes(found, primaryType) { + return found + } + if typedData.Types[primaryType] == nil { + return found + } + found = append(found, primaryType) + for _, field := range typedData.Types[primaryType] { + for _, dep := range typedData.Dependencies(field.Type, found) { + if !includes(found, dep) { + found = append(found, dep) + } + } + } + return found +} + +// EncodeType generates the following encoding: +// `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"` +// +// each member is written as `type ‖ " " ‖ name` encodings cascade down and are sorted by name +func (typedData *TypedData) EncodeType(primaryType string) hexutil.Bytes { + // Get dependencies primary first, then alphabetical + deps := typedData.Dependencies(primaryType, []string{}) + if len(deps) > 0 { + slicedDeps := deps[1:] + sort.Strings(slicedDeps) + deps = append([]string{primaryType}, slicedDeps...) + } + + // Format as a string with fields + var buffer bytes.Buffer + for _, dep := range deps { + buffer.WriteString(dep) + buffer.WriteString("(") + for _, obj := range typedData.Types[dep] { + buffer.WriteString(obj.Type) + buffer.WriteString(" ") + buffer.WriteString(obj.Name) + buffer.WriteString(",") + } + buffer.Truncate(buffer.Len() - 1) + buffer.WriteString(")") + } + return buffer.Bytes() +} + +// TypeHash creates the keccak256 hash of the data +func (typedData *TypedData) TypeHash(primaryType string) hexutil.Bytes { + return crypto.Keccak256(typedData.EncodeType(primaryType)) +} + +// EncodeData generates the following encoding: +// `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)` +// +// each encoded member is 32-byte long +func (typedData *TypedData) EncodeData(primaryType string, data map[string]interface{}, depth int) (hexutil.Bytes, error) { + if err := typedData.validate(); err != nil { + return nil, err + } + + buffer := bytes.Buffer{} + + // Verify extra data + if len(typedData.Types[primaryType]) < len(data) { + return nil, errors.New("there is extra data provided in the message") + } + + // Add typehash + buffer.Write(typedData.TypeHash(primaryType)) + + // Add field contents. Structs and arrays have special handlers. + for _, field := range typedData.Types[primaryType] { + encType := field.Type + encValue := data[field.Name] + if encType[len(encType)-1:] == "]" { + arrayValue, ok := encValue.([]interface{}) + if !ok { + return nil, dataMismatchError(encType, encValue) + } + + arrayBuffer := bytes.Buffer{} + parsedType := strings.Split(encType, "[")[0] + for _, item := range arrayValue { + if typedData.Types[parsedType] != nil { + mapValue, ok := item.(map[string]interface{}) + if !ok { + return nil, dataMismatchError(parsedType, item) + } + encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) + if err != nil { + return nil, err + } + arrayBuffer.Write(encodedData) + } else { + bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) + if err != nil { + return nil, err + } + arrayBuffer.Write(bytesValue) + } + } + + buffer.Write(crypto.Keccak256(arrayBuffer.Bytes())) + } else if typedData.Types[field.Type] != nil { + mapValue, ok := encValue.(map[string]interface{}) + if !ok { + return nil, dataMismatchError(encType, encValue) + } + encodedData, err := typedData.EncodeData(field.Type, mapValue, depth+1) + if err != nil { + return nil, err + } + buffer.Write(crypto.Keccak256(encodedData)) + } else { + byteValue, err := typedData.EncodePrimitiveValue(encType, encValue, depth) + if err != nil { + return nil, err + } + buffer.Write(byteValue) + } + } + return buffer.Bytes(), nil +} + +func parseInteger(encType string, encValue interface{}) (*big.Int, error) { + var ( + length int + signed = strings.HasPrefix(encType, "int") + b *big.Int + ) + if encType == "int" || encType == "uint" { + length = 256 + } else { + lengthStr := "" + if strings.HasPrefix(encType, "uint") { + lengthStr = strings.TrimPrefix(encType, "uint") + } else { + lengthStr = strings.TrimPrefix(encType, "int") + } + atoiSize, err := strconv.Atoi(lengthStr) + if err != nil { + return nil, fmt.Errorf("invalid size on integer: %v", lengthStr) + } + length = atoiSize + } + switch v := encValue.(type) { + case *math.HexOrDecimal256: + b = (*big.Int)(v) + case string: + var hexIntValue math.HexOrDecimal256 + if err := hexIntValue.UnmarshalText([]byte(v)); err != nil { + return nil, err + } + b = (*big.Int)(&hexIntValue) + case float64: + // JSON parses non-strings as float64. Fail if we cannot + // convert it losslessly + if float64(int64(v)) == v { + b = big.NewInt(int64(v)) + } else { + return nil, fmt.Errorf("invalid float value %v for type %v", v, encType) + } + } + if b == nil { + return nil, fmt.Errorf("invalid integer value %v/%v for type %v", encValue, reflect.TypeOf(encValue), encType) + } + if b.BitLen() > length { + return nil, fmt.Errorf("integer larger than '%v'", encType) + } + if !signed && b.Sign() == -1 { + return nil, fmt.Errorf("invalid negative value for unsigned type %v", encType) + } + return b, nil +} + +// EncodePrimitiveValue deals with the primitive values found +// while searching through the typed data +func (typedData *TypedData) EncodePrimitiveValue(encType string, encValue interface{}, depth int) ([]byte, error) { + switch encType { + case "address": + stringValue, ok := encValue.(string) + if !ok || !common.IsHexAddress(stringValue) { + return nil, dataMismatchError(encType, encValue) + } + retval := make([]byte, 32) + copy(retval[12:], common.HexToAddress(stringValue).Bytes()) + return retval, nil + case "bool": + boolValue, ok := encValue.(bool) + if !ok { + return nil, dataMismatchError(encType, encValue) + } + if boolValue { + return math.PaddedBigBytes(common.Big1, 32), nil + } + return math.PaddedBigBytes(common.Big0, 32), nil + case "string": + strVal, ok := encValue.(string) + if !ok { + return nil, dataMismatchError(encType, encValue) + } + return crypto.Keccak256([]byte(strVal)), nil + case "bytes": + bytesValue, ok := encValue.([]byte) + if !ok { + return nil, dataMismatchError(encType, encValue) + } + return crypto.Keccak256(bytesValue), nil + } + if strings.HasPrefix(encType, "bytes") { + lengthStr := strings.TrimPrefix(encType, "bytes") + length, err := strconv.Atoi(lengthStr) + if err != nil { + return nil, fmt.Errorf("invalid size on bytes: %v", lengthStr) + } + if length < 0 || length > 32 { + return nil, fmt.Errorf("invalid size on bytes: %d", length) + } + if byteValue, ok := encValue.(hexutil.Bytes); !ok { + return nil, dataMismatchError(encType, encValue) + } else { + return math.PaddedBigBytes(new(big.Int).SetBytes(byteValue), 32), nil + } + } + if strings.HasPrefix(encType, "int") || strings.HasPrefix(encType, "uint") { + b, err := parseInteger(encType, encValue) + if err != nil { + return nil, err + } + return abi.U256(b), nil + } + return nil, fmt.Errorf("unrecognized type '%s'", encType) + +} + +// dataMismatchError generates an error for a mismatch between +// the provided type and data +func dataMismatchError(encType string, encValue interface{}) error { + return fmt.Errorf("provided data '%v' doesn't match type '%s'", encValue, encType) +} + +// EcRecover recovers the address associated with the given sig. +// Only compatible with `text/plain` +func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { + // Returns the address for the Account that was used to create the signature. + // + // Note, this function is compatible with eth_sign and personal_sign. As such it recovers + // the address of: + // hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}") + // addr = ecrecover(hash, signature) + // + // Note, the signature must conform to the secp256k1 curve R, S and V values, where + // the V value must be be 27 or 28 for legacy reasons. + // + // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover + if len(sig) != 65 { + return common.Address{}, fmt.Errorf("signature must be 65 bytes long") + } + if sig[64] != 27 && sig[64] != 28 { + return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") + } + sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 + hash := accounts.TextHash(data) + rpk, err := crypto.SigToPub(hash, sig) + if err != nil { + return common.Address{}, err + } + return crypto.PubkeyToAddress(*rpk), nil +} + +// UnmarshalValidatorData converts the bytes input to typed data +func UnmarshalValidatorData(data interface{}) (ValidatorData, error) { + raw, ok := data.(map[string]interface{}) + if !ok { + return ValidatorData{}, errors.New("validator input is not a map[string]interface{}") + } + addr, ok := raw["address"].(string) + if !ok { + return ValidatorData{}, errors.New("validator address is not sent as a string") + } + addrBytes, err := hexutil.Decode(addr) + if err != nil { + return ValidatorData{}, err + } + if !ok || len(addrBytes) == 0 { + return ValidatorData{}, errors.New("validator address is undefined") + } + + message, ok := raw["message"].(string) + if !ok { + return ValidatorData{}, errors.New("message is not sent as a string") + } + messageBytes, err := hexutil.Decode(message) + if err != nil { + return ValidatorData{}, err + } + if !ok || len(messageBytes) == 0 { + return ValidatorData{}, errors.New("message is undefined") + } + + return ValidatorData{ + Address: common.BytesToAddress(addrBytes), + Message: messageBytes, + }, nil +} + +// validate makes sure the types are sound +func (typedData *TypedData) validate() error { + if err := typedData.Types.validate(); err != nil { + return err + } + if err := typedData.Domain.validate(); err != nil { + return err + } + return nil +} + +// Map generates a map version of the typed data +func (typedData *TypedData) Map() map[string]interface{} { + dataMap := map[string]interface{}{ + "types": typedData.Types, + "domain": typedData.Domain.Map(), + "primaryType": typedData.PrimaryType, + "message": typedData.Message, + } + return dataMap +} + +// Format returns a representation of typedData, which can be easily displayed by a user-interface +// without in-depth knowledge about 712 rules +func (typedData *TypedData) Format() ([]*NameValueType, error) { + domain, err := typedData.formatData("EIP712Domain", typedData.Domain.Map()) + if err != nil { + return nil, err + } + ptype, err := typedData.formatData(typedData.PrimaryType, typedData.Message) + if err != nil { + return nil, err + } + var nvts []*NameValueType + nvts = append(nvts, &NameValueType{ + Name: "EIP712Domain", + Value: domain, + Typ: "domain", + }) + nvts = append(nvts, &NameValueType{ + Name: typedData.PrimaryType, + Value: ptype, + Typ: "primary type", + }) + return nvts, nil +} + +func (typedData *TypedData) formatData(primaryType string, data map[string]interface{}) ([]*NameValueType, error) { + var output []*NameValueType + + // Add field contents. Structs and arrays have special handlers. + for _, field := range typedData.Types[primaryType] { + encName := field.Name + encValue := data[encName] + item := &NameValueType{ + Name: encName, + Typ: field.Type, + } + if field.isArray() { + arrayValue, _ := encValue.([]interface{}) + parsedType := field.typeName() + for _, v := range arrayValue { + if typedData.Types[parsedType] != nil { + mapValue, _ := v.(map[string]interface{}) + mapOutput, err := typedData.formatData(parsedType, mapValue) + if err != nil { + return nil, err + } + item.Value = mapOutput + } else { + primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) + if err != nil { + return nil, err + } + item.Value = primitiveOutput + } + } + } else if typedData.Types[field.Type] != nil { + if mapValue, ok := encValue.(map[string]interface{}); ok { + mapOutput, err := typedData.formatData(field.Type, mapValue) + if err != nil { + return nil, err + } + item.Value = mapOutput + } else { + item.Value = "" + } + } else { + primitiveOutput, err := formatPrimitiveValue(field.Type, encValue) + if err != nil { + return nil, err + } + item.Value = primitiveOutput + } + output = append(output, item) + } + return output, nil +} + +func formatPrimitiveValue(encType string, encValue interface{}) (string, error) { + switch encType { + case "address": + if stringValue, ok := encValue.(string); !ok { + return "", fmt.Errorf("could not format value %v as address", encValue) + } else { + return common.HexToAddress(stringValue).String(), nil + } + case "bool": + if boolValue, ok := encValue.(bool); !ok { + return "", fmt.Errorf("could not format value %v as bool", encValue) + } else { + return fmt.Sprintf("%t", boolValue), nil + } + case "bytes", "string": + return fmt.Sprintf("%s", encValue), nil + } + if strings.HasPrefix(encType, "bytes") { + return fmt.Sprintf("%s", encValue), nil + + } + if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") { + if b, err := parseInteger(encType, encValue); err != nil { + return "", err + } else { + return fmt.Sprintf("%d (0x%x)", b, b), nil + } + } + return "", fmt.Errorf("unhandled type %v", encType) +} + +// NameValueType is a very simple struct with Name, Value and Type. It's meant for simple +// json structures used to communicate signing-info about typed data with the UI +type NameValueType struct { + Name string `json:"name"` + Value interface{} `json:"value"` + Typ string `json:"type"` +} + +// Pprint returns a pretty-printed version of nvt +func (nvt *NameValueType) Pprint(depth int) string { + output := bytes.Buffer{} + output.WriteString(strings.Repeat("\u00a0", depth*2)) + output.WriteString(fmt.Sprintf("%s [%s]: ", nvt.Name, nvt.Typ)) + if nvts, ok := nvt.Value.([]*NameValueType); ok { + output.WriteString("\n") + for _, next := range nvts { + sublevel := next.Pprint(depth + 1) + output.WriteString(sublevel) + } + } else { + output.WriteString(fmt.Sprintf("%q\n", nvt.Value)) + } + return output.String() +} + +// Validate checks if the types object is conformant to the specs +func (t Types) validate() error { + for typeKey, typeArr := range t { + if len(typeKey) == 0 { + return fmt.Errorf("empty type key") + } + for i, typeObj := range typeArr { + if len(typeObj.Type) == 0 { + return fmt.Errorf("type %v:%d: empty Type", typeKey, i) + } + if len(typeObj.Name) == 0 { + return fmt.Errorf("type %v:%d: empty Name", typeKey, i) + } + if typeKey == typeObj.Type { + return fmt.Errorf("type '%s' cannot reference itself", typeObj.Type) + } + if typeObj.isReferenceType() { + if _, exist := t[typeObj.typeName()]; !exist { + return fmt.Errorf("reference type '%s' is undefined", typeObj.Type) + } + if !typedDataReferenceTypeRegexp.MatchString(typeObj.Type) { + return fmt.Errorf("unknown reference type '%s", typeObj.Type) + } + } else if !isPrimitiveTypeValid(typeObj.Type) { + return fmt.Errorf("unknown type '%s'", typeObj.Type) + } + } + } + return nil +} + +// Checks if the primitive value is valid +func isPrimitiveTypeValid(primitiveType string) bool { + if primitiveType == "address" || + primitiveType == "address[]" || + primitiveType == "bool" || + primitiveType == "bool[]" || + primitiveType == "string" || + primitiveType == "string[]" { + return true + } + if primitiveType == "bytes" || + primitiveType == "bytes[]" || + primitiveType == "bytes1" || + primitiveType == "bytes1[]" || + primitiveType == "bytes2" || + primitiveType == "bytes2[]" || + primitiveType == "bytes3" || + primitiveType == "bytes3[]" || + primitiveType == "bytes4" || + primitiveType == "bytes4[]" || + primitiveType == "bytes5" || + primitiveType == "bytes5[]" || + primitiveType == "bytes6" || + primitiveType == "bytes6[]" || + primitiveType == "bytes7" || + primitiveType == "bytes7[]" || + primitiveType == "bytes8" || + primitiveType == "bytes8[]" || + primitiveType == "bytes9" || + primitiveType == "bytes9[]" || + primitiveType == "bytes10" || + primitiveType == "bytes10[]" || + primitiveType == "bytes11" || + primitiveType == "bytes11[]" || + primitiveType == "bytes12" || + primitiveType == "bytes12[]" || + primitiveType == "bytes13" || + primitiveType == "bytes13[]" || + primitiveType == "bytes14" || + primitiveType == "bytes14[]" || + primitiveType == "bytes15" || + primitiveType == "bytes15[]" || + primitiveType == "bytes16" || + primitiveType == "bytes16[]" || + primitiveType == "bytes17" || + primitiveType == "bytes17[]" || + primitiveType == "bytes18" || + primitiveType == "bytes18[]" || + primitiveType == "bytes19" || + primitiveType == "bytes19[]" || + primitiveType == "bytes20" || + primitiveType == "bytes20[]" || + primitiveType == "bytes21" || + primitiveType == "bytes21[]" || + primitiveType == "bytes22" || + primitiveType == "bytes22[]" || + primitiveType == "bytes23" || + primitiveType == "bytes23[]" || + primitiveType == "bytes24" || + primitiveType == "bytes24[]" || + primitiveType == "bytes25" || + primitiveType == "bytes25[]" || + primitiveType == "bytes26" || + primitiveType == "bytes26[]" || + primitiveType == "bytes27" || + primitiveType == "bytes27[]" || + primitiveType == "bytes28" || + primitiveType == "bytes28[]" || + primitiveType == "bytes29" || + primitiveType == "bytes29[]" || + primitiveType == "bytes30" || + primitiveType == "bytes30[]" || + primitiveType == "bytes31" || + primitiveType == "bytes31[]" { + return true + } + if primitiveType == "int" || + primitiveType == "int[]" || + primitiveType == "int8" || + primitiveType == "int8[]" || + primitiveType == "int16" || + primitiveType == "int16[]" || + primitiveType == "int32" || + primitiveType == "int32[]" || + primitiveType == "int64" || + primitiveType == "int64[]" || + primitiveType == "int128" || + primitiveType == "int128[]" || + primitiveType == "int256" || + primitiveType == "int256[]" { + return true + } + if primitiveType == "uint" || + primitiveType == "uint[]" || + primitiveType == "uint8" || + primitiveType == "uint8[]" || + primitiveType == "uint16" || + primitiveType == "uint16[]" || + primitiveType == "uint32" || + primitiveType == "uint32[]" || + primitiveType == "uint64" || + primitiveType == "uint64[]" || + primitiveType == "uint128" || + primitiveType == "uint128[]" || + primitiveType == "uint256" || + primitiveType == "uint256[]" { + return true + } + return false +} + +// validate checks if the given domain is valid, i.e. contains at least +// the minimum viable keys and values +func (domain *TypedDataDomain) validate() error { + if domain.ChainId == nil { + return errors.New("chainId must be specified according to EIP-155") + } + + if len(domain.Name) == 0 && len(domain.Version) == 0 && len(domain.VerifyingContract) == 0 && len(domain.Salt) == 0 { + return errors.New("domain is undefined") + } + + return nil +} + +// Map is a helper function to generate a map version of the domain +func (domain *TypedDataDomain) Map() map[string]interface{} { + dataMap := map[string]interface{}{} + + if domain.ChainId != nil { + dataMap["chainId"] = domain.ChainId + } + + if len(domain.Name) > 0 { + dataMap["name"] = domain.Name + } + + if len(domain.Version) > 0 { + dataMap["version"] = domain.Version + } + + if len(domain.VerifyingContract) > 0 { + dataMap["verifyingContract"] = domain.VerifyingContract + } + + if len(domain.Salt) > 0 { + dataMap["salt"] = domain.Salt + } + return dataMap +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/stdioui.go b/vendor/github.com/ethereum/go-ethereum/signer/core/stdioui.go new file mode 100644 index 000000000..9ffe1398d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/stdioui.go @@ -0,0 +1,122 @@ +// 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 core + +import ( + "context" + "sync" + + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +type StdIOUI struct { + client rpc.Client + mu sync.Mutex +} + +func NewStdIOUI() *StdIOUI { + client, err := rpc.DialContext(context.Background(), "stdio://") + if err != nil { + log.Crit("Could not create stdio client", "err", err) + } + ui := &StdIOUI{client: *client} + return ui +} + +func (ui *StdIOUI) RegisterUIServer(api *UIServerAPI) { + ui.client.RegisterName("clef", api) +} + +// dispatch sends a request over the stdio +func (ui *StdIOUI) dispatch(serviceMethod string, args interface{}, reply interface{}) error { + err := ui.client.Call(&reply, serviceMethod, args) + if err != nil { + log.Info("Error", "exc", err.Error()) + } + return err +} + +// notify sends a request over the stdio, and does not listen for a response +func (ui *StdIOUI) notify(serviceMethod string, args interface{}) error { + ctx := context.Background() + err := ui.client.Notify(ctx, serviceMethod, args) + if err != nil { + log.Info("Error", "exc", err.Error()) + } + return err +} + +func (ui *StdIOUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) { + var result SignTxResponse + err := ui.dispatch("ui_approveTx", request, &result) + return result, err +} + +func (ui *StdIOUI) ApproveSignData(request *SignDataRequest) (SignDataResponse, error) { + var result SignDataResponse + err := ui.dispatch("ui_approveSignData", request, &result) + return result, err +} + +func (ui *StdIOUI) ApproveListing(request *ListRequest) (ListResponse, error) { + var result ListResponse + err := ui.dispatch("ui_approveListing", request, &result) + return result, err +} + +func (ui *StdIOUI) ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error) { + var result NewAccountResponse + err := ui.dispatch("ui_approveNewAccount", request, &result) + return result, err +} + +func (ui *StdIOUI) ShowError(message string) { + err := ui.notify("ui_showError", &Message{message}) + if err != nil { + log.Info("Error calling 'ui_showError'", "exc", err.Error(), "msg", message) + } +} + +func (ui *StdIOUI) ShowInfo(message string) { + err := ui.notify("ui_showInfo", Message{message}) + if err != nil { + log.Info("Error calling 'ui_showInfo'", "exc", err.Error(), "msg", message) + } +} +func (ui *StdIOUI) OnApprovedTx(tx ethapi.SignTransactionResult) { + err := ui.notify("ui_onApprovedTx", tx) + if err != nil { + log.Info("Error calling 'ui_onApprovedTx'", "exc", err.Error(), "tx", tx) + } +} + +func (ui *StdIOUI) OnSignerStartup(info StartupInfo) { + err := ui.notify("ui_onSignerStartup", info) + if err != nil { + log.Info("Error calling 'ui_onSignerStartup'", "exc", err.Error(), "info", info) + } +} +func (ui *StdIOUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) { + var result UserInputResponse + err := ui.dispatch("ui_onInputRequired", info, &result) + if err != nil { + log.Info("Error calling 'ui_onInputRequired'", "exc", err.Error(), "info", info) + } + return result, err +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/types.go b/vendor/github.com/ethereum/go-ethereum/signer/core/types.go new file mode 100644 index 000000000..f147f06cd --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/types.go @@ -0,0 +1,100 @@ +// 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 core + +import ( + "encoding/json" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +) + +type ValidationInfo struct { + Typ string `json:"type"` + Message string `json:"message"` +} +type ValidationMessages struct { + Messages []ValidationInfo +} + +const ( + WARN = "WARNING" + CRIT = "CRITICAL" + INFO = "Info" +) + +func (vs *ValidationMessages) Crit(msg string) { + vs.Messages = append(vs.Messages, ValidationInfo{CRIT, msg}) +} +func (vs *ValidationMessages) Warn(msg string) { + vs.Messages = append(vs.Messages, ValidationInfo{WARN, msg}) +} +func (vs *ValidationMessages) Info(msg string) { + vs.Messages = append(vs.Messages, ValidationInfo{INFO, msg}) +} + +/// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present +func (v *ValidationMessages) getWarnings() error { + var messages []string + for _, msg := range v.Messages { + if msg.Typ == WARN || msg.Typ == CRIT { + messages = append(messages, msg.Message) + } + } + if len(messages) > 0 { + return fmt.Errorf("Validation failed: %s", strings.Join(messages, ",")) + } + return nil +} + +// SendTxArgs represents the arguments to submit a transaction +type SendTxArgs struct { + From common.MixedcaseAddress `json:"from"` + To *common.MixedcaseAddress `json:"to"` + Gas hexutil.Uint64 `json:"gas"` + GasPrice hexutil.Big `json:"gasPrice"` + Value hexutil.Big `json:"value"` + Nonce hexutil.Uint64 `json:"nonce"` + // We accept "data" and "input" for backwards-compatibility reasons. + Data *hexutil.Bytes `json:"data"` + Input *hexutil.Bytes `json:"input,omitempty"` +} + +func (args SendTxArgs) String() string { + s, err := json.Marshal(args) + if err == nil { + return string(s) + } + return err.Error() +} + +func (args *SendTxArgs) toTransaction() *types.Transaction { + var input []byte + if args.Data != nil { + input = *args.Data + } else if args.Input != nil { + input = *args.Input + } + if args.To == nil { + return types.NewContractCreation(uint64(args.Nonce), (*big.Int)(&args.Value), uint64(args.Gas), (*big.Int)(&args.GasPrice), input) + } + return types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (uint64)(args.Gas), (*big.Int)(&args.GasPrice), input) +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/uiapi.go b/vendor/github.com/ethereum/go-ethereum/signer/core/uiapi.go new file mode 100644 index 000000000..7c2d233f8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/uiapi.go @@ -0,0 +1,200 @@ +// Copyright 2019 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 core + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" +) + +// SignerUIAPI implements methods Clef provides for a UI to query, in the bidirectional communication +// channel. +// This API is considered secure, since a request can only +// ever arrive from the UI -- and the UI is capable of approving any action, thus we can consider these +// requests pre-approved. +// NB: It's very important that these methods are not ever exposed on the external service +// registry. +type UIServerAPI struct { + extApi *SignerAPI + am *accounts.Manager +} + +// NewUIServerAPI creates a new UIServerAPI +func NewUIServerAPI(extapi *SignerAPI) *UIServerAPI { + return &UIServerAPI{extapi, extapi.am} +} + +// List available accounts. As opposed to the external API definition, this method delivers +// the full Account object and not only Address. +// Example call +// {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4} +func (s *UIServerAPI) ListAccounts(ctx context.Context) ([]accounts.Account, error) { + var accs []accounts.Account + for _, wallet := range s.am.Wallets() { + accs = append(accs, wallet.Accounts()...) + } + return accs, nil +} + +// rawWallet is a JSON representation of an accounts.Wallet interface, with its +// data contents extracted into plain fields. +type rawWallet struct { + URL string `json:"url"` + Status string `json:"status"` + Failure string `json:"failure,omitempty"` + Accounts []accounts.Account `json:"accounts,omitempty"` +} + +// ListWallets will return a list of wallets that clef manages +// Example call +// {"jsonrpc":"2.0","method":"clef_listWallets","params":[], "id":5} +func (s *UIServerAPI) ListWallets() []rawWallet { + wallets := make([]rawWallet, 0) // return [] instead of nil if empty + for _, wallet := range s.am.Wallets() { + status, failure := wallet.Status() + + raw := rawWallet{ + URL: wallet.URL().String(), + Status: status, + Accounts: wallet.Accounts(), + } + if failure != nil { + raw.Failure = failure.Error() + } + wallets = append(wallets, raw) + } + return wallets +} + +// DeriveAccount requests a HD wallet to derive a new account, optionally pinning +// it for later reuse. +// Example call +// {"jsonrpc":"2.0","method":"clef_deriveAccount","params":["ledger://","m/44'/60'/0'", false], "id":6} +func (s *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) { + wallet, err := s.am.Wallet(url) + if err != nil { + return accounts.Account{}, err + } + derivPath, err := accounts.ParseDerivationPath(path) + if err != nil { + return accounts.Account{}, err + } + if pin == nil { + pin = new(bool) + } + return wallet.Derive(derivPath, *pin) +} + +// fetchKeystore retrives the encrypted keystore from the account manager. +func fetchKeystore(am *accounts.Manager) *keystore.KeyStore { + return am.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) +} + +// ImportRawKey stores the given hex encoded ECDSA key into the key directory, +// encrypting it with the passphrase. +// Example call (should fail on password too short) +// {"jsonrpc":"2.0","method":"clef_importRawKey","params":["1111111111111111111111111111111111111111111111111111111111111111","test"], "id":6} +func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Account, error) { + key, err := crypto.HexToECDSA(privkey) + if err != nil { + return accounts.Account{}, err + } + if err := ValidatePasswordFormat(password); err != nil { + return accounts.Account{}, fmt.Errorf("password requirements not met: %v", err) + } + // No error + return fetchKeystore(s.am).ImportECDSA(key, password) +} + +// OpenWallet initiates a hardware wallet opening procedure, establishing a USB +// connection and attempting to authenticate via the provided passphrase. Note, +// the method may return an extra challenge requiring a second open (e.g. the +// Trezor PIN matrix challenge). +// Example +// {"jsonrpc":"2.0","method":"clef_openWallet","params":["ledger://",""], "id":6} +func (s *UIServerAPI) OpenWallet(url string, passphrase *string) error { + wallet, err := s.am.Wallet(url) + if err != nil { + return err + } + pass := "" + if passphrase != nil { + pass = *passphrase + } + return wallet.Open(pass) +} + +// ChainId returns the chainid in use for Eip-155 replay protection +// Example call +// {"jsonrpc":"2.0","method":"clef_chainId","params":[], "id":8} +func (s *UIServerAPI) ChainId() math.HexOrDecimal64 { + return (math.HexOrDecimal64)(s.extApi.chainID.Uint64()) +} + +// SetChainId sets the chain id to use when signing transactions. +// Example call to set Ropsten: +// {"jsonrpc":"2.0","method":"clef_setChainId","params":["3"], "id":8} +func (s *UIServerAPI) SetChainId(id math.HexOrDecimal64) math.HexOrDecimal64 { + s.extApi.chainID = new(big.Int).SetUint64(uint64(id)) + return s.ChainId() +} + +// Export returns encrypted private key associated with the given address in web3 keystore format. +// Example +// {"jsonrpc":"2.0","method":"clef_export","params":["0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a"], "id":4} +func (s *UIServerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) { + // Look up the wallet containing the requested signer + wallet, err := s.am.Find(accounts.Account{Address: addr}) + if err != nil { + return nil, err + } + if wallet.URL().Scheme != keystore.KeyStoreScheme { + return nil, fmt.Errorf("Account is not a keystore-account") + } + return ioutil.ReadFile(wallet.URL().Path) +} + +// Import tries to import the given keyJSON in the local keystore. The keyJSON data is expected to be +// in web3 keystore format. It will decrypt the keyJSON with the given passphrase and on successful +// decryption it will encrypt the key with the given newPassphrase and store it in the keystore. +// Example (the address in question has privkey `11...11`): +// {"jsonrpc":"2.0","method":"clef_import","params":[{"address":"19e7e376e7c213b7e7e7e46cc70a5dd086daff2a","crypto":{"cipher":"aes-128-ctr","ciphertext":"33e4cd3756091d037862bb7295e9552424a391a6e003272180a455ca2a9fb332","cipherparams":{"iv":"b54b263e8f89c42bb219b6279fba5cce"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e4ca94644fd30569c1b1afbbc851729953c92637b7fe4bb9840bbb31ffbc64a5"},"mac":"f4092a445c2b21c0ef34f17c9cd0d873702b2869ec5df4439a0c2505823217e7"},"id":"216c7eac-e8c1-49af-a215-fa0036f29141","version":3},"test","yaddayadda"], "id":4} +func (api *UIServerAPI) Import(ctx context.Context, keyJSON json.RawMessage, oldPassphrase, newPassphrase string) (accounts.Account, error) { + be := api.am.Backends(keystore.KeyStoreType) + + if len(be) == 0 { + return accounts.Account{}, errors.New("password based accounts not supported") + } + if err := ValidatePasswordFormat(newPassphrase); err != nil { + return accounts.Account{}, fmt.Errorf("password requirements not met: %v", err) + } + return be[0].(*keystore.KeyStore).Import(keyJSON, oldPassphrase, newPassphrase) +} + +// Other methods to be added, not yet implemented are: +// - Ruleset interaction: add rules, attest rulefiles +// - Store metadata about accounts, e.g. naming of accounts diff --git a/vendor/github.com/ethereum/go-ethereum/signer/core/validation.go b/vendor/github.com/ethereum/go-ethereum/signer/core/validation.go new file mode 100644 index 000000000..af858862e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/core/validation.go @@ -0,0 +1,36 @@ +// 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 core + +import ( + "errors" + "regexp" +) + +var printable7BitAscii = regexp.MustCompile("^[A-Za-z0-9!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ]+$") + +// ValidatePasswordFormat returns an error if the password is too short, or consists of characters +// outside the range of the printable 7bit ascii set +func ValidatePasswordFormat(password string) error { + if len(password) < 10 { + return errors.New("password too short (<10 characters)") + } + if !printable7BitAscii.MatchString(password) { + return errors.New("password contains invalid characters - only 7bit printable ascii allowed") + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/storage/aes_gcm_storage.go b/vendor/github.com/ethereum/go-ethereum/signer/storage/aes_gcm_storage.go new file mode 100644 index 000000000..8c5e147ac --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/storage/aes_gcm_storage.go @@ -0,0 +1,179 @@ +// 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 storage + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/json" + "io" + "io/ioutil" + "os" + + "github.com/ethereum/go-ethereum/log" +) + +type storedCredential struct { + // The iv + Iv []byte `json:"iv"` + // The ciphertext + CipherText []byte `json:"c"` +} + +// AESEncryptedStorage is a storage type which is backed by a json-file. The json-file contains +// key-value mappings, where the keys are _not_ encrypted, only the values are. +type AESEncryptedStorage struct { + // File to read/write credentials + filename string + // Key stored in base64 + key []byte +} + +// NewAESEncryptedStorage creates a new encrypted storage backed by the given file/key +func NewAESEncryptedStorage(filename string, key []byte) *AESEncryptedStorage { + return &AESEncryptedStorage{ + filename: filename, + key: key, + } +} + +// Put stores a value by key. 0-length keys results in noop. +func (s *AESEncryptedStorage) Put(key, value string) { + if len(key) == 0 { + return + } + data, err := s.readEncryptedStorage() + if err != nil { + log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) + return + } + ciphertext, iv, err := encrypt(s.key, []byte(value), []byte(key)) + if err != nil { + log.Warn("Failed to encrypt entry", "err", err) + return + } + encrypted := storedCredential{Iv: iv, CipherText: ciphertext} + data[key] = encrypted + if err = s.writeEncryptedStorage(data); err != nil { + log.Warn("Failed to write entry", "err", err) + } +} + +// Get returns the previously stored value, or an error if it does not exist or +// key is of 0-length. +func (s *AESEncryptedStorage) Get(key string) (string, error) { + if len(key) == 0 { + return "", ErrZeroKey + } + data, err := s.readEncryptedStorage() + if err != nil { + log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) + return "", err + } + encrypted, exist := data[key] + if !exist { + log.Warn("Key does not exist", "key", key) + return "", ErrNotFound + } + entry, err := decrypt(s.key, encrypted.Iv, encrypted.CipherText, []byte(key)) + if err != nil { + log.Warn("Failed to decrypt key", "key", key) + return "", err + } + return string(entry), nil +} + +// Del removes a key-value pair. If the key doesn't exist, the method is a noop. +func (s *AESEncryptedStorage) Del(key string) { + data, err := s.readEncryptedStorage() + if err != nil { + log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) + return + } + delete(data, key) + if err = s.writeEncryptedStorage(data); err != nil { + log.Warn("Failed to write entry", "err", err) + } +} + +// readEncryptedStorage reads the file with encrypted creds +func (s *AESEncryptedStorage) readEncryptedStorage() (map[string]storedCredential, error) { + creds := make(map[string]storedCredential) + raw, err := ioutil.ReadFile(s.filename) + + if err != nil { + if os.IsNotExist(err) { + // Doesn't exist yet + return creds, nil + } + log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename) + } + if err = json.Unmarshal(raw, &creds); err != nil { + log.Warn("Failed to unmarshal encrypted storage", "err", err, "file", s.filename) + return nil, err + } + return creds, nil +} + +// writeEncryptedStorage write the file with encrypted creds +func (s *AESEncryptedStorage) writeEncryptedStorage(creds map[string]storedCredential) error { + raw, err := json.Marshal(creds) + if err != nil { + return err + } + if err = ioutil.WriteFile(s.filename, raw, 0600); err != nil { + return err + } + return nil +} + +// encrypt encrypts plaintext with the given key, with additional data +// The 'additionalData' is used to place the (plaintext) KV-store key into the V, +// to prevent the possibility to alter a K, or swap two entries in the KV store with eachother. +func encrypt(key []byte, plaintext []byte, additionalData []byte) ([]byte, []byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, nil, err + } + aesgcm, err := cipher.NewGCM(block) + nonce := make([]byte, aesgcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return nil, nil, err + } + if err != nil { + return nil, nil, err + } + ciphertext := aesgcm.Seal(nil, nonce, plaintext, additionalData) + return ciphertext, nonce, nil +} + +func decrypt(key []byte, nonce []byte, ciphertext []byte, additionalData []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + aesgcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + plaintext, err := aesgcm.Open(nil, nonce, ciphertext, additionalData) + if err != nil { + return nil, err + } + return plaintext, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/signer/storage/storage.go b/vendor/github.com/ethereum/go-ethereum/signer/storage/storage.go new file mode 100644 index 000000000..06b0fd98f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/signer/storage/storage.go @@ -0,0 +1,87 @@ +// 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 storage + +import "errors" + +var ( + // ErrZeroKey is returned if an attempt was made to inset a 0-length key. + ErrZeroKey = errors.New("0-length key") + + // ErrNotFound is returned if an unknown key is attempted to be retrieved. + ErrNotFound = errors.New("not found") +) + +type Storage interface { + // Put stores a value by key. 0-length keys results in noop. + Put(key, value string) + + // Get returns the previously stored value, or an error if the key is 0-length + // or unknown. + Get(key string) (string, error) + + // Del removes a key-value pair. If the key doesn't exist, the method is a noop. + Del(key string) +} + +// EphemeralStorage is an in-memory storage that does +// not persist values to disk. Mainly used for testing +type EphemeralStorage struct { + data map[string]string + namespace string +} + +// Put stores a value by key. 0-length keys results in noop. +func (s *EphemeralStorage) Put(key, value string) { + if len(key) == 0 { + return + } + s.data[key] = value +} + +// Get returns the previously stored value, or an error if the key is 0-length +// or unknown. +func (s *EphemeralStorage) Get(key string) (string, error) { + if len(key) == 0 { + return "", ErrZeroKey + } + if v, ok := s.data[key]; ok { + return v, nil + } + return "", ErrNotFound +} + +// Del removes a key-value pair. If the key doesn't exist, the method is a noop. +func (s *EphemeralStorage) Del(key string) { + delete(s.data, key) +} + +func NewEphemeralStorage() Storage { + s := &EphemeralStorage{ + data: make(map[string]string), + } + return s +} + +// NoStorage is a dummy construct which doesn't remember anything you tell it +type NoStorage struct{} + +func (s *NoStorage) Put(key, value string) {} +func (s *NoStorage) Del(key string) {} +func (s *NoStorage) Get(key string) (string, error) { + return "", errors.New("I forgot") +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/database.go b/vendor/github.com/ethereum/go-ethereum/trie/database.go index c39af85cf..d8a0fa9c5 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/database.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/database.go @@ -17,9 +17,11 @@ package trie import ( + "encoding/binary" "errors" "fmt" "io" + "reflect" "sync" "time" @@ -56,20 +58,16 @@ var secureKeyPrefix = []byte("secure-key-") // secureKeyLength is the length of the above prefix + 32byte hash. const secureKeyLength = 11 + 32 -// DatabaseReader wraps the Get and Has method of a backing store for the trie. -type DatabaseReader interface { - // Get retrieves the value associated with key from the database. - Get(key []byte) (value []byte, err error) - - // Has retrieves whether a key is present in the database. - Has(key []byte) (bool, error) -} - // Database is an intermediate write layer between the trie data structures and // the disk database. The aim is to accumulate trie writes in-memory and only // periodically flush a couple tries to disk, garbage collecting the remainder. +// +// Note, the trie Database is **not** thread safe in its mutations, but it **is** +// thread safe in providing individual, independent node access. The rationale +// behind this split design is to provide read access to RPC handlers and sync +// servers even while the trie is executing expensive garbage collection. type Database struct { - diskdb ethdb.Database // Persistent storage for matured trie nodes + diskdb ethdb.KeyValueStore // Persistent storage for matured trie nodes cleans *bigcache.BigCache // GC friendly memory cache of clean node RLPs dirties map[common.Hash]*cachedNode // Data and references relationships of dirty nodes @@ -87,7 +85,8 @@ type Database struct { flushnodes uint64 // Nodes flushed since last commit flushsize common.StorageSize // Data storage flushed since last commit - dirtiesSize common.StorageSize // Storage size of the dirty node cache (exc. flushlist) + dirtiesSize common.StorageSize // Storage size of the dirty node cache (exc. metadata) + childrenSize common.StorageSize // Storage size of the external children tracking preimagesSize common.StorageSize // Storage size of the preimages cache lock sync.RWMutex @@ -149,6 +148,15 @@ type cachedNode struct { flushNext common.Hash // Next node in the flush-list } +// cachedNodeSize is the raw size of a cachedNode data structure without any +// node data included. It's an approximate size, but should be a lot better +// than not counting them. +var cachedNodeSize = int(reflect.TypeOf(cachedNode{}).Size()) + +// cachedNodeChildrenSize is the raw size of an initialized but empty external +// reference map. +const cachedNodeChildrenSize = 48 + // rlp returns the raw rlp encoded blob of the cached node, either directly from // the cache, or by regenerating it from the collapsed node. func (n *cachedNode) rlp() []byte { @@ -164,11 +172,11 @@ func (n *cachedNode) rlp() []byte { // obj returns the decoded and expanded trie node, either directly from the cache, // or by regenerating it from the rlp encoded blob. -func (n *cachedNode) obj(hash common.Hash, cachegen uint16) node { +func (n *cachedNode) obj(hash common.Hash) node { if node, ok := n.node.(rawNode); ok { - return mustDecodeNode(hash[:], node, cachegen) + return mustDecodeNode(hash[:], node) } - return expandNode(hash[:], n.node, cachegen) + return expandNode(hash[:], n.node) } // childs returns all the tracked children of this node, both the implicit ones @@ -233,16 +241,15 @@ func simplifyNode(n node) node { // expandNode traverses the node hierarchy of a collapsed storage node and converts // all fields and keys into expanded memory form. -func expandNode(hash hashNode, n node, cachegen uint16) node { +func expandNode(hash hashNode, n node) node { switch n := n.(type) { case *rawShortNode: // Short nodes need key and child expansion return &shortNode{ Key: compactToHex(n.Key), - Val: expandNode(nil, n.Val, cachegen), + Val: expandNode(nil, n.Val), flags: nodeFlag{ hash: hash, - gen: cachegen, }, } @@ -251,12 +258,11 @@ func expandNode(hash hashNode, n node, cachegen uint16) node { node := &fullNode{ flags: nodeFlag{ hash: hash, - gen: cachegen, }, } for i := 0; i < len(node.Children); i++ { if n[i] != nil { - node.Children[i] = expandNode(nil, n[i], cachegen) + node.Children[i] = expandNode(nil, n[i]) } } return node @@ -269,17 +275,30 @@ func expandNode(hash hashNode, n node, cachegen uint16) node { } } +// trienodeHasher is a struct to be used with BigCache, which uses a Hasher to +// determine which shard to place an entry into. It's not a cryptographic hash, +// just to provide a bit of anti-collision (default is FNV64a). +// +// Since trie keys are already hashes, we can just use the key directly to +// map shard id. +type trienodeHasher struct{} + +// Sum64 implements the bigcache.Hasher interface. +func (t trienodeHasher) Sum64(key string) uint64 { + return binary.BigEndian.Uint64([]byte(key)) +} + // NewDatabase creates a new trie database to store ephemeral trie content before // its written out to disk or garbage collected. No read cache is created, so all // data retrievals will hit the underlying disk database. -func NewDatabase(diskdb ethdb.Database) *Database { +func NewDatabase(diskdb ethdb.KeyValueStore) *Database { return NewDatabaseWithCache(diskdb, 0) } // NewDatabaseWithCache creates a new trie database to store ephemeral trie content // before its written out to disk or garbage collected. It also acts as a read cache // for nodes loaded from disk. -func NewDatabaseWithCache(diskdb ethdb.Database, cache int) *Database { +func NewDatabaseWithCache(diskdb ethdb.KeyValueStore, cache int) *Database { var cleans *bigcache.BigCache if cache > 0 { cleans, _ = bigcache.NewBigCache(bigcache.Config{ @@ -288,18 +307,21 @@ func NewDatabaseWithCache(diskdb ethdb.Database, cache int) *Database { MaxEntriesInWindow: cache * 1024, MaxEntrySize: 512, HardMaxCacheSize: cache, + Hasher: trienodeHasher{}, }) } return &Database{ - diskdb: diskdb, - cleans: cleans, - dirties: map[common.Hash]*cachedNode{{}: {}}, + diskdb: diskdb, + cleans: cleans, + dirties: map[common.Hash]*cachedNode{{}: { + children: make(map[common.Hash]uint16), + }}, preimages: make(map[common.Hash][]byte), } } // DiskDB retrieves the persistent storage backing the trie database. -func (db *Database) DiskDB() DatabaseReader { +func (db *Database) DiskDB() ethdb.KeyValueReader { return db.diskdb } @@ -359,13 +381,13 @@ func (db *Database) insertPreimage(hash common.Hash, preimage []byte) { // node retrieves a cached trie node from memory, or returns nil if none can be // found in the memory cache. -func (db *Database) node(hash common.Hash, cachegen uint16) node { +func (db *Database) node(hash common.Hash) node { // Retrieve the node from the clean cache if available if db.cleans != nil { if enc, err := db.cleans.Get(string(hash[:])); err == nil && enc != nil { memcacheCleanHitMeter.Mark(1) memcacheCleanReadMeter.Mark(int64(len(enc))) - return mustDecodeNode(hash[:], enc, cachegen) + return mustDecodeNode(hash[:], enc) } } // Retrieve the node from the dirty cache if available @@ -374,7 +396,7 @@ func (db *Database) node(hash common.Hash, cachegen uint16) node { db.lock.RUnlock() if dirty != nil { - return dirty.obj(hash, cachegen) + return dirty.obj(hash) } // Content unavailable in memory, attempt to retrieve from disk enc, err := db.diskdb.Get(hash[:]) @@ -386,7 +408,7 @@ func (db *Database) node(hash common.Hash, cachegen uint16) node { memcacheCleanMissMeter.Mark(1) memcacheCleanWriteMeter.Mark(int64(len(enc))) } - return mustDecodeNode(hash[:], enc, cachegen) + return mustDecodeNode(hash[:], enc) } // Node retrieves an encoded cached trie node from memory. If it cannot be found @@ -466,8 +488,8 @@ func (db *Database) Nodes() []common.Hash { // Reference adds a new reference from a parent node to a child node. func (db *Database) Reference(child common.Hash, parent common.Hash) { - db.lock.RLock() - defer db.lock.RUnlock() + db.lock.Lock() + defer db.lock.Unlock() db.reference(child, parent) } @@ -482,11 +504,15 @@ func (db *Database) reference(child common.Hash, parent common.Hash) { // If the reference already exists, only duplicate for roots if db.dirties[parent].children == nil { db.dirties[parent].children = make(map[common.Hash]uint16) + db.childrenSize += cachedNodeChildrenSize } else if _, ok = db.dirties[parent].children[child]; ok && parent != (common.Hash{}) { return } node.parents++ db.dirties[parent].children[child]++ + if db.dirties[parent].children[child] == 1 { + db.childrenSize += common.HashLength + 2 // uint16 counter + } } // Dereference removes an existing reference from a root node. @@ -523,6 +549,7 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) { node.children[child]-- if node.children[child] == 0 { delete(node.children, child) + db.childrenSize -= (common.HashLength + 2) // uint16 counter } } // If the child does not exist, it's a previously committed node. @@ -557,25 +584,30 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) { } delete(db.dirties, child) db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + if node.children != nil { + db.childrenSize -= cachedNodeChildrenSize + } } } // Cap iteratively flushes old but still referenced trie nodes until the total // memory usage goes below the given threshold. +// +// Note, this method is a non-synchronized mutator. It is unsafe to call this +// concurrently with other mutators. func (db *Database) Cap(limit common.StorageSize) error { // Create a database batch to flush persistent data out. It is important that // outside code doesn't see an inconsistent state (referenced data removed from // memory cache during commit but not yet in persistent storage). This is ensured // by only uncaching existing data when the database write finalizes. - db.lock.RLock() - nodes, storage, start := len(db.dirties), db.dirtiesSize, time.Now() batch := db.diskdb.NewBatch() // db.dirtiesSize only contains the useful data in the cache, but when reporting // the total memory consumption, the maintenance metadata is also needed to be - // counted. For every useful node, we track 2 extra hashes as the flushlist. - size := db.dirtiesSize + common.StorageSize((len(db.dirties)-1)*2*common.HashLength) + // counted. + size := db.dirtiesSize + common.StorageSize((len(db.dirties)-1)*cachedNodeSize) + size += db.childrenSize - common.StorageSize(len(db.dirties[common.Hash{}].children)*(common.HashLength+2)) // If the preimage cache got large enough, push to disk. If it's still small // leave for later to deduplicate writes. @@ -584,12 +616,10 @@ func (db *Database) Cap(limit common.StorageSize) error { for hash, preimage := range db.preimages { if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { log.Error("Failed to commit preimage from trie database", "err", err) - db.lock.RUnlock() return err } if batch.ValueSize() > ethdb.IdealBatchSize { if err := batch.Write(); err != nil { - db.lock.RUnlock() return err } batch.Reset() @@ -602,33 +632,30 @@ func (db *Database) Cap(limit common.StorageSize) error { // Fetch the oldest referenced node and push into the batch node := db.dirties[oldest] if err := batch.Put(oldest[:], node.rlp()); err != nil { - db.lock.RUnlock() return err } // If we exceeded the ideal batch size, commit and reset if batch.ValueSize() >= ethdb.IdealBatchSize { if err := batch.Write(); err != nil { log.Error("Failed to write flush list to disk", "err", err) - db.lock.RUnlock() return err } batch.Reset() } // Iterate to the next flush item, or abort if the size cap was achieved. Size - // is the total size, including both the useful cached data (hash -> blob), as - // well as the flushlist metadata (2*hash). When flushing items from the cache, - // we need to reduce both. - size -= common.StorageSize(3*common.HashLength + int(node.size)) + // is the total size, including the useful cached data (hash -> blob), the + // cache item metadata, as well as external children mappings. + size -= common.StorageSize(common.HashLength + int(node.size) + cachedNodeSize) + if node.children != nil { + size -= common.StorageSize(cachedNodeChildrenSize + len(node.children)*(common.HashLength+2)) + } oldest = node.flushNext } // Flush out any remainder data from the last batch if err := batch.Write(); err != nil { log.Error("Failed to write flush list to disk", "err", err) - db.lock.RUnlock() return err } - db.lock.RUnlock() - // Write successful, clear out the flushed data db.lock.Lock() defer db.lock.Unlock() @@ -643,6 +670,9 @@ func (db *Database) Cap(limit common.StorageSize) error { db.oldest = node.flushNext db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + if node.children != nil { + db.childrenSize -= common.StorageSize(cachedNodeChildrenSize + len(node.children)*(common.HashLength+2)) + } } if db.oldest != (common.Hash{}) { db.dirties[db.oldest].flushPrev = common.Hash{} @@ -662,16 +692,16 @@ func (db *Database) Cap(limit common.StorageSize) error { } // Commit iterates over all the children of a particular node, writes them out -// to disk, forcefully tearing down all references in both directions. +// to disk, forcefully tearing down all references in both directions. As a side +// effect, all pre-images accumulated up to this point are also written. // -// As a side effect, all pre-images accumulated up to this point are also written. +// Note, this method is a non-synchronized mutator. It is unsafe to call this +// concurrently with other mutators. func (db *Database) Commit(node common.Hash, report bool) error { // Create a database batch to flush persistent data out. It is important that // outside code doesn't see an inconsistent state (referenced data removed from // memory cache during commit but not yet in persistent storage). This is ensured // by only uncaching existing data when the database write finalizes. - db.lock.RLock() - start := time.Now() batch := db.diskdb.NewBatch() @@ -679,9 +709,9 @@ func (db *Database) Commit(node common.Hash, report bool) error { for hash, preimage := range db.preimages { if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { log.Error("Failed to commit preimage from trie database", "err", err) - db.lock.RUnlock() return err } + // If the batch is too large, flush to disk if batch.ValueSize() > ethdb.IdealBatchSize { if err := batch.Write(); err != nil { return err @@ -689,30 +719,37 @@ func (db *Database) Commit(node common.Hash, report bool) error { batch.Reset() } } + // Since we're going to replay trie node writes into the clean cache, flush out + // any batched pre-images before continuing. + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + // Move the trie itself into the batch, flushing if enough data is accumulated nodes, storage := len(db.dirties), db.dirtiesSize - if err := db.commit(node, batch); err != nil { + + uncacher := &cleaner{db} + if err := db.commit(node, batch, uncacher); err != nil { log.Error("Failed to commit trie from trie database", "err", err) - db.lock.RUnlock() return err } - // Write batch ready, unlock for readers during persistence + // Trie mostly committed to disk, flush any batch leftovers if err := batch.Write(); err != nil { log.Error("Failed to write trie to disk", "err", err) - db.lock.RUnlock() return err } - db.lock.RUnlock() - - // Write successful, clear out the flushed data + // Uncache any leftovers in the last batch db.lock.Lock() defer db.lock.Unlock() + batch.Replay(uncacher) + batch.Reset() + + // Reset the storage counters and bumpd metrics db.preimages = make(map[common.Hash][]byte) db.preimagesSize = 0 - db.uncache(node) - memcacheCommitTimeTimer.Update(time.Since(start)) memcacheCommitSizeMeter.Mark(int64(storage - db.dirtiesSize)) memcacheCommitNodesMeter.Mark(int64(nodes - len(db.dirties))) @@ -732,14 +769,14 @@ func (db *Database) Commit(node common.Hash, report bool) error { } // commit is the private locked version of Commit. -func (db *Database) commit(hash common.Hash, batch ethdb.Batch) error { +func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleaner) error { // If the node does not exist, it's a previously committed node node, ok := db.dirties[hash] if !ok { return nil } for _, child := range node.childs() { - if err := db.commit(child, batch); err != nil { + if err := db.commit(child, batch, uncacher); err != nil { return err } } @@ -751,39 +788,60 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch) error { if err := batch.Write(); err != nil { return err } + db.lock.Lock() + batch.Replay(uncacher) batch.Reset() + db.lock.Unlock() } return nil } -// uncache is the post-processing step of a commit operation where the already -// persisted trie is removed from the cache. The reason behind the two-phase -// commit is to ensure consistent data availability while moving from memory -// to disk. -func (db *Database) uncache(hash common.Hash) { +// cleaner is a database batch replayer that takes a batch of write operations +// and cleans up the trie database from anything written to disk. +type cleaner struct { + db *Database +} + +// Put reacts to database writes and implements dirty data uncaching. This is the +// post-processing step of a commit operation where the already persisted trie is +// removed from the dirty cache and moved into the clean cache. The reason behind +// the two-phase commit is to ensure ensure data availability while moving from +// memory to disk. +func (c *cleaner) Put(key []byte, rlp []byte) error { + hash := common.BytesToHash(key) + // If the node does not exist, we're done on this path - node, ok := db.dirties[hash] + node, ok := c.db.dirties[hash] if !ok { - return + return nil } // Node still exists, remove it from the flush-list switch hash { - case db.oldest: - db.oldest = node.flushNext - db.dirties[node.flushNext].flushPrev = common.Hash{} - case db.newest: - db.newest = node.flushPrev - db.dirties[node.flushPrev].flushNext = common.Hash{} + case c.db.oldest: + c.db.oldest = node.flushNext + c.db.dirties[node.flushNext].flushPrev = common.Hash{} + case c.db.newest: + c.db.newest = node.flushPrev + c.db.dirties[node.flushPrev].flushNext = common.Hash{} default: - db.dirties[node.flushPrev].flushNext = node.flushNext - db.dirties[node.flushNext].flushPrev = node.flushPrev + c.db.dirties[node.flushPrev].flushNext = node.flushNext + c.db.dirties[node.flushNext].flushPrev = node.flushPrev } - // Uncache the node's subtries and remove the node itself too - for _, child := range node.childs() { - db.uncache(child) + // Remove the node from the dirty cache + delete(c.db.dirties, hash) + c.db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + if node.children != nil { + c.db.dirtiesSize -= common.StorageSize(cachedNodeChildrenSize + len(node.children)*(common.HashLength+2)) } - delete(db.dirties, hash) - db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size)) + // Move the flushed node into the clean cache to prevent insta-reloads + if c.db.cleans != nil { + c.db.cleans.Set(string(hash[:]), rlp) + } + return nil +} + +func (c *cleaner) Delete(key []byte) error { + panic("Not implemented") } // Size returns the current storage size of the memory cache in front of the @@ -794,9 +852,10 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize) { // db.dirtiesSize only contains the useful data in the cache, but when reporting // the total memory consumption, the maintenance metadata is also needed to be - // counted. For every useful node, we track 2 extra hashes as the flushlist. - var flushlistSize = common.StorageSize((len(db.dirties) - 1) * 2 * common.HashLength) - return db.dirtiesSize + flushlistSize, db.preimagesSize + // counted. + var metadataSize = common.StorageSize((len(db.dirties) - 1) * cachedNodeSize) + var metarootRefs = common.StorageSize(len(db.dirties[common.Hash{}].children) * (common.HashLength + 2)) + return db.dirtiesSize + db.childrenSize + metadataSize - metarootRefs, db.preimagesSize } // verifyIntegrity is a debug method to iterate over the entire trie stored in @@ -813,7 +872,7 @@ func (db *Database) verifyIntegrity() { db.accumulate(child, reachable) } // Find any unreachable but cached nodes - unreachable := []string{} + var unreachable []string for hash, node := range db.dirties { if _, ok := reachable[hash]; !ok { unreachable = append(unreachable, fmt.Sprintf("%x: {Node: %v, Parents: %d, Prev: %x, Next: %x}", diff --git a/vendor/github.com/ethereum/go-ethereum/trie/hasher.go b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go index 9d6756b6f..54f6a9de2 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/hasher.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go @@ -26,11 +26,9 @@ import ( ) type hasher struct { - tmp sliceBuffer - sha keccakState - cachegen uint16 - cachelimit uint16 - onleaf LeafCallback + tmp sliceBuffer + sha keccakState + onleaf LeafCallback } // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports @@ -62,9 +60,9 @@ var hasherPool = sync.Pool{ }, } -func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher { +func newHasher(onleaf LeafCallback) *hasher { h := hasherPool.Get().(*hasher) - h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf + h.onleaf = onleaf return h } @@ -80,14 +78,13 @@ func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) { if db == nil { return hash, n, nil } - if n.canUnload(h.cachegen, h.cachelimit) { - // Unload the node from cache. All of its subnodes will have a lower or equal - // cache generation number. - cacheUnloadCounter.Inc(1) - return hash, hash, nil - } if !dirty { - return hash, n, nil + switch n.(type) { + case *fullNode, *shortNode: + return hash, hash, nil + default: + return hash, n, nil + } } } // Trie not processed yet or needs storage, walk the children diff --git a/vendor/github.com/ethereum/go-ethereum/trie/iterator.go b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go index 77f168166..8e84dee3b 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/iterator.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go @@ -34,7 +34,9 @@ type Iterator struct { Err error } -// NewIterator creates a new key-value iterator from a node iterator +// NewIterator creates a new key-value iterator from a node iterator. +// Note that the value returned by the iterator is raw. If the content is encoded +// (e.g. storage value is RLP-encoded), it's caller's duty to decode it. func NewIterator(it NodeIterator) *Iterator { return &Iterator{ nodeIt: it, @@ -180,7 +182,7 @@ func (it *nodeIterator) LeafBlob() []byte { func (it *nodeIterator) LeafProof() [][]byte { if len(it.stack) > 0 { if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { - hasher := newHasher(0, 0, nil) + hasher := newHasher(nil) defer returnHasherToPool(hasher) proofs := make([][]byte, 0, len(it.stack)) diff --git a/vendor/github.com/ethereum/go-ethereum/trie/node.go b/vendor/github.com/ethereum/go-ethereum/trie/node.go index 1fafb7a53..f4055e779 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/node.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/node.go @@ -30,7 +30,6 @@ var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b type node interface { fstring(string) string cache() (hashNode, bool) - canUnload(cachegen, cachelimit uint16) bool } type ( @@ -71,20 +70,9 @@ func (n *shortNode) copy() *shortNode { copy := *n; return © } // nodeFlag contains caching-related metadata about a node. type nodeFlag struct { hash hashNode // cached hash of the node (may be nil) - gen uint16 // cache generation counter dirty bool // whether the node has changes that must be written to the database } -// canUnload tells whether a node can be unloaded. -func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool { - return !n.dirty && cachegen-n.gen >= cachelimit -} - -func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } -func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } -func (n hashNode) canUnload(uint16, uint16) bool { return false } -func (n valueNode) canUnload(uint16, uint16) bool { return false } - func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } func (n hashNode) cache() (hashNode, bool) { return nil, true } @@ -117,8 +105,8 @@ func (n valueNode) fstring(ind string) string { return fmt.Sprintf("%x ", []byte(n)) } -func mustDecodeNode(hash, buf []byte, cachegen uint16) node { - n, err := decodeNode(hash, buf, cachegen) +func mustDecodeNode(hash, buf []byte) node { + n, err := decodeNode(hash, buf) if err != nil { panic(fmt.Sprintf("node %x: %v", hash, err)) } @@ -126,7 +114,7 @@ func mustDecodeNode(hash, buf []byte, cachegen uint16) node { } // decodeNode parses the RLP encoding of a trie node. -func decodeNode(hash, buf []byte, cachegen uint16) (node, error) { +func decodeNode(hash, buf []byte) (node, error) { if len(buf) == 0 { return nil, io.ErrUnexpectedEOF } @@ -136,22 +124,22 @@ func decodeNode(hash, buf []byte, cachegen uint16) (node, error) { } switch c, _ := rlp.CountValues(elems); c { case 2: - n, err := decodeShort(hash, elems, cachegen) + n, err := decodeShort(hash, elems) return n, wrapError(err, "short") case 17: - n, err := decodeFull(hash, elems, cachegen) + n, err := decodeFull(hash, elems) return n, wrapError(err, "full") default: return nil, fmt.Errorf("invalid number of list elements: %v", c) } } -func decodeShort(hash, elems []byte, cachegen uint16) (node, error) { +func decodeShort(hash, elems []byte) (node, error) { kbuf, rest, err := rlp.SplitString(elems) if err != nil { return nil, err } - flag := nodeFlag{hash: hash, gen: cachegen} + flag := nodeFlag{hash: hash} key := compactToHex(kbuf) if hasTerm(key) { // value node @@ -161,17 +149,17 @@ func decodeShort(hash, elems []byte, cachegen uint16) (node, error) { } return &shortNode{key, append(valueNode{}, val...), flag}, nil } - r, _, err := decodeRef(rest, cachegen) + r, _, err := decodeRef(rest) if err != nil { return nil, wrapError(err, "val") } return &shortNode{key, r, flag}, nil } -func decodeFull(hash, elems []byte, cachegen uint16) (*fullNode, error) { - n := &fullNode{flags: nodeFlag{hash: hash, gen: cachegen}} +func decodeFull(hash, elems []byte) (*fullNode, error) { + n := &fullNode{flags: nodeFlag{hash: hash}} for i := 0; i < 16; i++ { - cld, rest, err := decodeRef(elems, cachegen) + cld, rest, err := decodeRef(elems) if err != nil { return n, wrapError(err, fmt.Sprintf("[%d]", i)) } @@ -189,7 +177,7 @@ func decodeFull(hash, elems []byte, cachegen uint16) (*fullNode, error) { const hashLen = len(common.Hash{}) -func decodeRef(buf []byte, cachegen uint16) (node, []byte, error) { +func decodeRef(buf []byte) (node, []byte, error) { kind, val, rest, err := rlp.Split(buf) if err != nil { return nil, buf, err @@ -202,7 +190,7 @@ func decodeRef(buf []byte, cachegen uint16) (node, []byte, error) { err := fmt.Errorf("oversized embedded node (size is %d bytes, want size < %d)", size, hashLen) return nil, buf, err } - n, err := decodeNode(nil, buf, cachegen) + n, err := decodeNode(nil, buf) return n, rest, err case kind == rlp.String && len(val) == 0: // empty node diff --git a/vendor/github.com/ethereum/go-ethereum/trie/proof.go b/vendor/github.com/ethereum/go-ethereum/trie/proof.go index f90ecd7d8..9985e730d 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/proof.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/proof.go @@ -21,7 +21,6 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -34,10 +33,10 @@ import ( // If the trie does not contain a value for key, the returned proof contains all // nodes of the longest existing prefix of the key (at least the root node), ending // with the node that proves the absence of the key. -func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { +func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error { // Collect all nodes on the path to key. key = keybytesToHex(key) - nodes := []node{} + var nodes []node tn := t.root for len(key) > 0 && tn != nil { switch n := tn.(type) { @@ -65,7 +64,7 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) } } - hasher := newHasher(0, 0, nil) + hasher := newHasher(nil) defer returnHasherToPool(hasher) for i, n := range nodes { @@ -81,7 +80,7 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { } else { enc, _ := rlp.EncodeToBytes(n) if !ok { - hash = crypto.Keccak256(enc) + hash = hasher.makeHashNode(enc) } proofDb.Put(hash, enc) } @@ -97,14 +96,14 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { // If the trie does not contain a value for key, the returned proof contains all // nodes of the longest existing prefix of the key (at least the root node), ending // with the node that proves the absence of the key. -func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { +func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error { return t.trie.Prove(key, fromLevel, proofDb) } // VerifyProof checks merkle proofs. The given proof must contain the value for // key in a trie with the given root hash. VerifyProof returns an error if the // proof contains invalid trie nodes or the wrong value. -func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, nodes int, err error) { +func VerifyProof(rootHash common.Hash, key []byte, proofDb ethdb.KeyValueReader) (value []byte, nodes int, err error) { key = keybytesToHex(key) wantHash := rootHash for i := 0; ; i++ { @@ -112,7 +111,7 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (valu if buf == nil { return nil, i, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash) } - n, err := decodeNode(wantHash[:], buf, 0) + n, err := decodeNode(wantHash[:], buf) if err != nil { return nil, i, fmt.Errorf("bad proof node %d: %v", i, err) } diff --git a/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go index 6a50cfd5a..fbc591ed1 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go @@ -51,7 +51,7 @@ type SecureTrie struct { // Loaded nodes are kept around until their 'cache generation' expires. // A new cache generation is created by each call to Commit. // cachelimit sets the number of past cache generations to keep. -func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, error) { +func NewSecure(root common.Hash, db *Database) (*SecureTrie, error) { if db == nil { panic("trie.NewSecure called without a database") } @@ -59,7 +59,6 @@ func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, if err != nil { return nil, err } - trie.SetCacheLimit(cachelimit) return &SecureTrie{trie: *trie}, nil } @@ -161,12 +160,6 @@ func (t *SecureTrie) Hash() common.Hash { return t.trie.Hash() } -// Root returns the root hash of SecureTrie. -// Deprecated: use Hash instead. -func (t *SecureTrie) Root() []byte { - return t.trie.Root() -} - // Copy returns a copy of SecureTrie. func (t *SecureTrie) Copy() *SecureTrie { cpy := *t @@ -183,7 +176,7 @@ func (t *SecureTrie) NodeIterator(start []byte) NodeIterator { // The caller must not hold onto the return value because it will become // invalid on the next call to hashKey or secKey. func (t *SecureTrie) hashKey(key []byte) []byte { - h := newHasher(0, 0, nil) + h := newHasher(nil) h.sha.Reset() h.sha.Write(key) buf := h.sha.Sum(t.hashKeyBuf[:0]) diff --git a/vendor/github.com/ethereum/go-ethereum/trie/sync.go b/vendor/github.com/ethereum/go-ethereum/trie/sync.go index 67dff5a8b..6f40b45a1 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/sync.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/sync.go @@ -72,19 +72,21 @@ func newSyncMemBatch() *syncMemBatch { // unknown trie hashes to retrieve, accepts node data associated with said hashes // and reconstructs the trie step by step until all is done. type Sync struct { - database DatabaseReader // Persistent database to check for existing entries + database ethdb.KeyValueReader // Persistent database to check for existing entries membatch *syncMemBatch // Memory buffer to avoid frequent database writes requests map[common.Hash]*request // Pending requests pertaining to a key hash queue *prque.Prque // Priority queue with the pending requests + bloom *SyncBloom // Bloom filter for fast node existence checks } // NewSync creates a new trie data download scheduler. -func NewSync(root common.Hash, database DatabaseReader, callback LeafCallback) *Sync { +func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallback, bloom *SyncBloom) *Sync { ts := &Sync{ database: database, membatch: newSyncMemBatch(), requests: make(map[common.Hash]*request), queue: prque.New(nil), + bloom: bloom, } ts.AddSubTrie(root, 0, common.Hash{}, callback) return ts @@ -99,10 +101,14 @@ func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callb if _, ok := s.membatch.batch[root]; ok { return } - key := root.Bytes() - blob, _ := s.database.Get(key) - if local, err := decodeNode(key, blob, 0); local != nil && err == nil { - return + if s.bloom.Contains(root[:]) { + // Bloom filter says this might be a duplicate, double check + blob, _ := s.database.Get(root[:]) + if local, err := decodeNode(root[:], blob); local != nil && err == nil { + return + } + // False positive, bump fault meter + bloomFaultMeter.Mark(1) } // Assemble the new sub-trie sync request req := &request{ @@ -134,8 +140,13 @@ func (s *Sync) AddRawEntry(hash common.Hash, depth int, parent common.Hash) { if _, ok := s.membatch.batch[hash]; ok { return } - if ok, _ := s.database.Has(hash.Bytes()); ok { - return + if s.bloom.Contains(hash[:]) { + // Bloom filter says this might be a duplicate, double check + if ok, _ := s.database.Has(hash[:]); ok { + return + } + // False positive, bump fault meter + bloomFaultMeter.Mark(1) } // Assemble the new sub-trie sync request req := &request{ @@ -157,7 +168,7 @@ func (s *Sync) AddRawEntry(hash common.Hash, depth int, parent common.Hash) { // Missing retrieves the known missing nodes from the trie for retrieval. func (s *Sync) Missing(max int) []common.Hash { - requests := []common.Hash{} + var requests []common.Hash for !s.queue.Empty() && (max == 0 || len(requests) < max) { requests = append(requests, s.queue.PopItem().(common.Hash)) } @@ -187,7 +198,7 @@ func (s *Sync) Process(results []SyncResult) (bool, int, error) { continue } // Decode the node data content and update the request - node, err := decodeNode(item.Hash[:], item.Data, 0) + node, err := decodeNode(item.Hash[:], item.Data) if err != nil { return committed, i, err } @@ -213,14 +224,15 @@ func (s *Sync) Process(results []SyncResult) (bool, int, error) { // Commit flushes the data stored in the internal membatch out to persistent // storage, returning the number of items written and any occurred error. -func (s *Sync) Commit(dbw ethdb.Putter) (int, error) { +func (s *Sync) Commit(dbw ethdb.KeyValueWriter) (int, error) { // Dump the membatch into a database dbw for i, key := range s.membatch.order { if err := dbw.Put(key[:], s.membatch.batch[key]); err != nil { return i, err } + s.bloom.Add(key[:]) } - written := len(s.membatch.order) + written := len(s.membatch.order) // TODO(karalabe): could an order change improve write performance? // Drop the membatch data and return s.membatch = newSyncMemBatch() @@ -254,7 +266,7 @@ func (s *Sync) children(req *request, object node) ([]*request, error) { node node depth int } - children := []child{} + var children []child switch node := (object).(type) { case *shortNode: @@ -292,8 +304,13 @@ func (s *Sync) children(req *request, object node) ([]*request, error) { if _, ok := s.membatch.batch[hash]; ok { continue } - if ok, _ := s.database.Has(node); ok { - continue + if s.bloom.Contains(node) { + // Bloom filter says this might be a duplicate, double check + if ok, _ := s.database.Has(node); ok { + continue + } + // False positive, bump fault meter + bloomFaultMeter.Mark(1) } // Locally unknown node, schedule for retrieval requests = append(requests, &request{ diff --git a/vendor/github.com/ethereum/go-ethereum/trie/sync_bloom.go b/vendor/github.com/ethereum/go-ethereum/trie/sync_bloom.go new file mode 100644 index 000000000..2182d1c43 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/sync_bloom.go @@ -0,0 +1,207 @@ +// Copyright 2019 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 trie + +import ( + "encoding/binary" + "fmt" + "math" + "sync" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/steakknife/bloomfilter" +) + +var ( + bloomAddMeter = metrics.NewRegisteredMeter("trie/bloom/add", nil) + bloomLoadMeter = metrics.NewRegisteredMeter("trie/bloom/load", nil) + bloomTestMeter = metrics.NewRegisteredMeter("trie/bloom/test", nil) + bloomMissMeter = metrics.NewRegisteredMeter("trie/bloom/miss", nil) + bloomFaultMeter = metrics.NewRegisteredMeter("trie/bloom/fault", nil) + bloomErrorGauge = metrics.NewRegisteredGauge("trie/bloom/error", nil) +) + +// syncBloomHasher is a wrapper around a byte blob to satisfy the interface API +// requirements of the bloom library used. It's used to convert a trie hash into +// a 64 bit mini hash. +type syncBloomHasher []byte + +func (f syncBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") } +func (f syncBloomHasher) Sum(b []byte) []byte { panic("not implemented") } +func (f syncBloomHasher) Reset() { panic("not implemented") } +func (f syncBloomHasher) BlockSize() int { panic("not implemented") } +func (f syncBloomHasher) Size() int { return 8 } +func (f syncBloomHasher) Sum64() uint64 { return binary.BigEndian.Uint64(f) } + +// SyncBloom is a bloom filter used during fast sync to quickly decide if a trie +// node already exists on disk or not. It self populates from the provided disk +// database on creation in a background thread and will only start returning live +// results once that's finished. +type SyncBloom struct { + bloom *bloomfilter.Filter + inited uint32 + closer sync.Once + closed uint32 + pend sync.WaitGroup +} + +// NewSyncBloom creates a new bloom filter of the given size (in megabytes) and +// initializes it from the database. The bloom is hard coded to use 3 filters. +func NewSyncBloom(memory uint64, database ethdb.Iteratee) *SyncBloom { + // Create the bloom filter to track known trie nodes + bloom, err := bloomfilter.New(memory*1024*1024*8, 3) + if err != nil { + panic(fmt.Sprintf("failed to create bloom: %v", err)) + } + log.Info("Allocated fast sync bloom", "size", common.StorageSize(memory*1024*1024)) + + // Assemble the fast sync bloom and init it from previous sessions + b := &SyncBloom{ + bloom: bloom, + } + b.pend.Add(2) + go func() { + defer b.pend.Done() + b.init(database) + }() + go func() { + defer b.pend.Done() + b.meter() + }() + return b +} + +// init iterates over the database, pushing every trie hash into the bloom filter. +func (b *SyncBloom) init(database ethdb.Iteratee) { + // Iterate over the database, but restart every now and again to avoid holding + // a persistent snapshot since fast sync can push a ton of data concurrently, + // bloating the disk. + // + // Note, this is fine, because everything inserted into leveldb by fast sync is + // also pushed into the bloom directly, so we're not missing anything when the + // iterator is swapped out for a new one. + it := database.NewIterator() + + var ( + start = time.Now() + swap = time.Now() + ) + for it.Next() && atomic.LoadUint32(&b.closed) == 0 { + // If the database entry is a trie node, add it to the bloom + if key := it.Key(); len(key) == common.HashLength { + b.bloom.Add(syncBloomHasher(key)) + bloomLoadMeter.Mark(1) + } + // If enough time elapsed since the last iterator swap, restart + if time.Since(swap) > 8*time.Second { + key := common.CopyBytes(it.Key()) + + it.Release() + it = database.NewIteratorWithStart(key) + + log.Info("Initializing fast sync bloom", "items", b.bloom.N(), "errorrate", b.errorRate(), "elapsed", common.PrettyDuration(time.Since(start))) + swap = time.Now() + } + } + it.Release() + + // Mark the bloom filter inited and return + log.Info("Initialized fast sync bloom", "items", b.bloom.N(), "errorrate", b.errorRate(), "elapsed", common.PrettyDuration(time.Since(start))) + atomic.StoreUint32(&b.inited, 1) +} + +// meter periodically recalculates the false positive error rate of the bloom +// filter and reports it in a metric. +func (b *SyncBloom) meter() { + for { + // Report the current error ration. No floats, lame, scale it up. + bloomErrorGauge.Update(int64(b.errorRate() * 100000)) + + // Wait one second, but check termination more frequently + for i := 0; i < 10; i++ { + if atomic.LoadUint32(&b.closed) == 1 { + return + } + time.Sleep(100 * time.Millisecond) + } + } +} + +// Close terminates any background initializer still running and releases all the +// memory allocated for the bloom. +func (b *SyncBloom) Close() error { + b.closer.Do(func() { + // Ensure the initializer is stopped + atomic.StoreUint32(&b.closed, 1) + b.pend.Wait() + + // Wipe the bloom, but mark it "uninited" just in case someone attempts an access + log.Info("Deallocated fast sync bloom", "items", b.bloom.N(), "errorrate", b.errorRate()) + + atomic.StoreUint32(&b.inited, 0) + b.bloom = nil + }) + return nil +} + +// Add inserts a new trie node hash into the bloom filter. +func (b *SyncBloom) Add(hash []byte) { + if atomic.LoadUint32(&b.closed) == 1 { + return + } + b.bloom.Add(syncBloomHasher(hash)) + bloomAddMeter.Mark(1) +} + +// Contains tests if the bloom filter contains the given hash: +// - false: the bloom definitely does not contain hash +// - true: the bloom maybe contains hash +// +// While the bloom is being initialized, any query will return true. +func (b *SyncBloom) Contains(hash []byte) bool { + bloomTestMeter.Mark(1) + if atomic.LoadUint32(&b.inited) == 0 { + // We didn't load all the trie nodes from the previous run of Geth yet. As + // such, we can't say for sure if a hash is not present for anything. Until + // the init is done, we're faking "possible presence" for everything. + return true + } + // Bloom initialized, check the real one and report any successful misses + maybe := b.bloom.Contains(syncBloomHasher(hash)) + if !maybe { + bloomMissMeter.Mark(1) + } + return maybe +} + +// errorRate calculates the probability of a random containment test returning a +// false positive. +// +// We're calculating it ourselves because the bloom library we used missed a +// parentheses in the formula and calculates it wrong. And it's discontinued... +func (b *SyncBloom) errorRate() float64 { + k := float64(b.bloom.K()) + n := float64(b.bloom.N()) + m := float64(b.bloom.M()) + + return math.Pow(1.0-math.Exp((-k)*(n+0.5)/(m-1)), k) +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/trie.go b/vendor/github.com/ethereum/go-ethereum/trie/trie.go index af424d4ac..920e331fd 100644 --- a/vendor/github.com/ethereum/go-ethereum/trie/trie.go +++ b/vendor/github.com/ethereum/go-ethereum/trie/trie.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" ) var ( @@ -35,25 +34,6 @@ var ( emptyState = crypto.Keccak256Hash(nil) ) -var ( - cacheMissCounter = metrics.NewRegisteredCounter("trie/cachemiss", nil) - cacheUnloadCounter = metrics.NewRegisteredCounter("trie/cacheunload", nil) -) - -// CacheMisses retrieves a global counter measuring the number of cache misses -// the trie had since process startup. This isn't useful for anything apart from -// trie debugging purposes. -func CacheMisses() int64 { - return cacheMissCounter.Count() -} - -// CacheUnloads retrieves a global counter measuring the number of cache unloads -// the trie did since process startup. This isn't useful for anything apart from -// trie debugging purposes. -func CacheUnloads() int64 { - return cacheUnloadCounter.Count() -} - // LeafCallback is a callback type invoked when a trie operation reaches a leaf // node. It's used by state sync and commit to allow handling external references // between account and storage tries. @@ -67,23 +47,11 @@ type LeafCallback func(leaf []byte, parent common.Hash) error type Trie struct { db *Database root node - - // Cache generation values. - // cachegen increases by one with each commit operation. - // new nodes are tagged with the current generation and unloaded - // when their generation is older than than cachegen-cachelimit. - cachegen, cachelimit uint16 -} - -// SetCacheLimit sets the number of 'cache generations' to keep. -// A cache generation is created by a call to Commit. -func (t *Trie) SetCacheLimit(l uint16) { - t.cachelimit = l } // newFlag returns the cache flag value for a newly created node. func (t *Trie) newFlag() nodeFlag { - return nodeFlag{dirty: true, gen: t.cachegen} + return nodeFlag{dirty: true} } // New creates a trie with an existing root node from db. @@ -152,14 +120,12 @@ func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode if err == nil && didResolve { n = n.copy() n.Val = newnode - n.flags.gen = t.cachegen } return value, n, didResolve, err case *fullNode: value, newnode, didResolve, err = t.tryGet(n.Children[key[pos]], key, pos+1) if err == nil && didResolve { n = n.copy() - n.flags.gen = t.cachegen n.Children[key[pos]] = newnode } return value, n, didResolve, err @@ -428,19 +394,13 @@ func (t *Trie) resolve(n node, prefix []byte) (node, error) { } func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) { - cacheMissCounter.Inc(1) - hash := common.BytesToHash(n) - if node := t.db.node(hash, t.cachegen); node != nil { + if node := t.db.node(hash); node != nil { return node, nil } return nil, &MissingNodeError{NodeHash: hash, Path: prefix} } -// Root returns the root hash of the trie. -// Deprecated: use Hash instead. -func (t *Trie) Root() []byte { return t.Hash().Bytes() } - // Hash returns the root hash of the trie. It does not write to the // database and can be used even if the trie doesn't have one. func (t *Trie) Hash() common.Hash { @@ -460,7 +420,6 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) { return common.Hash{}, err } t.root = cached - t.cachegen++ return common.BytesToHash(hash.(hashNode)), nil } @@ -468,7 +427,7 @@ func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) { if t.root == nil { return hashNode(emptyRoot.Bytes()), nil, nil } - h := newHasher(t.cachegen, t.cachelimit, onleaf) + h := newHasher(onleaf) defer returnHasherToPool(h) return h.hash(t.root, db, true) } diff --git a/vendor/github.com/gballet/go-libpcsclite/.gitignore b/vendor/github.com/gballet/go-libpcsclite/.gitignore new file mode 100644 index 000000000..f1c181ec9 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/.gitignore @@ -0,0 +1,12 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/vendor/github.com/gballet/go-libpcsclite/LICENSE b/vendor/github.com/gballet/go-libpcsclite/LICENSE new file mode 100644 index 000000000..52d9e62b0 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Guillaume Ballet +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gballet/go-libpcsclite/README.md b/vendor/github.com/gballet/go-libpcsclite/README.md new file mode 100644 index 000000000..182398e39 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/README.md @@ -0,0 +1,73 @@ +# go-libpcsclite + +A golang implementation of the [libpcpsclite](http://github.com/LudovicRousseau/PCSC) client. It connects to the `pcscd` daemon over sockets. + +## Purpose + +The goal is for major open source projects to distribute a single binary that doesn't depend on `libpcsclite`. It provides an extra function `CheckPCSCDaemon` that will tell the user if `pcscd` is running. + +## Example + +```golang +func main() { + client, err := EstablishContext(2) + if err != nil { + fmt.Printf("Error establishing context: %v\n", err) + os.Exit(1) + } + + _, err = client.ListReaders() + if err != nil { + fmt.Printf("Error getting the list of readers: %v\n", err) + os.Exit(1) + } + + card, err := client.Connect(client.readerStateDescriptors[0].Name, ShareShared, ProtocolT0|ProtocolT1) + if err != nil { + fmt.Printf("Error connecting: %v\n", err) + os.Exit(1) + } + + resp, _, err := card.Transmit([]byte{0, 0xa4, 4, 0, 0xA0, 0, 0, 8, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}) + + card.Disconnect(LeaveCard) +} +``` + +## TODO + + - [x] Finish this README + - [x] Lock context + - [ ] implement missing functions + +## License + +BSD 3-Clause License + +Copyright (c) 2019, Guillaume Ballet +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gballet/go-libpcsclite/doc.go b/vendor/github.com/gballet/go-libpcsclite/doc.go new file mode 100644 index 000000000..0f28c0c9c --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc.go @@ -0,0 +1,95 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package pcsc + +const ( + AutoAllocate = -1 /* see SCardFreeMemory() */ + ScopeUser = 0x0000 /* Scope in user space */ + ScopeTerminal = 0x0001 /* Scope in terminal */ + ScopeSystem = 0x0002 /* Scope in system */ + ScopeGlobal = 0x0003 /* Scope is global */ + + ProtocolUndefined = 0x0000 /* protocol not set */ + ProtocolUnSet = ProtocolUndefined /* backward compat */ + ProtocolT0 = 0x0001 /* T=0 active protocol. */ + ProtocolT1 = 0x0002 /* T=1 active protocol. */ + ProtocolRaw = 0x0004 /* Raw active protocol. */ + ProtocolT15 = 0x0008 /* T=15 protocol. */ + ProtocolAny = (ProtocolT0 | ProtocolT1) /* IFD determines prot. */ + + ShareExclusive = 0x0001 /* Exclusive mode only */ + ShareShared = 0x0002 /* Shared mode only */ + ShareDirect = 0x0003 /* Raw mode only */ + + LeaveCard = 0x0000 /* Do nothing on close */ + ResetCard = 0x0001 /* Reset on close */ + UnpowerCard = 0x0002 /* Power down on close */ + EjectCard = 0x0003 /* Eject on close */ + + SCardUnknown = 0x0001 /* Unknown state */ + SCardAbsent = 0x0002 /* Card is absent */ + SCardPresent = 0x0004 /* Card is present */ + SCardSwallowed = 0x0008 /* Card not powered */ + SCardPowever = 0x0010 /* Card is powered */ + SCardNegotiable = 0x0020 /* Ready for PTS */ + SCardSpecific = 0x0040 /* PTS has been set */ +) + +// List of commands to send to the daemon +const ( + _ = iota + SCardEstablishContext /* used by SCardEstablishContext() */ + SCardReleaseContext /* used by SCardReleaseContext() */ + SCardListReaders /* used by SCardListReaders() */ + SCardConnect /* used by SCardConnect() */ + SCardReConnect /* used by SCardReconnect() */ + SCardDisConnect /* used by SCardDisconnect() */ + SCardBeginTransaction /* used by SCardBeginTransaction() */ + SCardEndTransaction /* used by SCardEndTransaction() */ + SCardTransmit /* used by SCardTransmit() */ + SCardControl /* used by SCardControl() */ + SCardStatus /* used by SCardStatus() */ + SCardGetStatusChange /* not used */ + SCardCancel /* used by SCardCancel() */ + SCardCancelTransaction /* not used */ + SCardGetAttrib /* used by SCardGetAttrib() */ + SCardSetAttrib /* used by SCardSetAttrib() */ + CommandVersion /* get the client/server protocol version */ + CommandGetReaderState /* get the readers state */ + CommandWaitReaderStateChange /* wait for a reader state change */ + CommandStopWaitingReaderStateChange /* stop waiting for a reader state change */ +) + +// Protocol information +const ( + ProtocolVersionMajor = uint32(4) /* IPC major */ + ProtocolVersionMinor = uint32(3) /* IPC minor */ +) diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go b/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go new file mode 100644 index 000000000..672c672e4 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc_bsd.go @@ -0,0 +1,35 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build dragonfly freebsd netbsd openbsd solaris + +package pcsc + +const PCSCDSockName string = "/var/run/pcscd/pcscd.comm" diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go b/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go new file mode 100644 index 000000000..3dec7c79b --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc_darwin.go @@ -0,0 +1,35 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build darwin + +package pcsc + +const PCSCDSockName string = "" diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_linux.go b/vendor/github.com/gballet/go-libpcsclite/doc_linux.go new file mode 100644 index 000000000..becbf1677 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc_linux.go @@ -0,0 +1,35 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build linux + +package pcsc + +const PCSCDSockName string = "/run/pcscd/pcscd.comm" \ No newline at end of file diff --git a/vendor/github.com/gballet/go-libpcsclite/doc_windows.go b/vendor/github.com/gballet/go-libpcsclite/doc_windows.go new file mode 100644 index 000000000..9bd6bd333 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/doc_windows.go @@ -0,0 +1,35 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +build windows + +package pcsc + +const PCSCDSockName string = "" diff --git a/vendor/github.com/gballet/go-libpcsclite/error.go b/vendor/github.com/gballet/go-libpcsclite/error.go new file mode 100644 index 000000000..4710de5e6 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/error.go @@ -0,0 +1,246 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package pcsc + +import "fmt" + +type ErrorCode uint32 + +const ( + SCardSuccess ErrorCode = 0x00000000 /* No error was encountered. */ + ErrSCardInternal = 0x80100001 /* An internal consistency check failed. */ + ErrSCardCancelled = 0x80100002 /* The action was cancelled by an SCardCancel request. */ + ErrSCardInvalidHandle = 0x80100003 /* The supplied handle was invalid. */ + ErrSCardInvalidParameter = 0x80100004 /* One or more of the supplied parameters could not be properly interpreted. */ + ErrSCardInvalidTarget = 0x80100005 /* Registry startup information is missing or invalid. */ + ErrSCardNoMemory = 0x80100006 /* Not enough memory available to complete this command. */ + ErrSCardWaitedTooLong = 0x80100007 /* An internal consistency timer has expired. */ + ErrSCardInsufficientBuffer = 0x80100008 /* The data buffer to receive returned data is too small for the returned data. */ + ErrScardUnknownReader = 0x80100009 /* The specified reader name is not recognized. */ + ErrSCardTimeout = 0x8010000A /* The user-specified timeout value has expired. */ + ErrSCardSharingViolation = 0x8010000B /* The smart card cannot be accessed because of other connections outstanding. */ + ErrSCardNoSmartCard = 0x8010000C /* The operation requires a Smart Card, but no Smart Card is currently in the device. */ + ErrSCardUnknownCard = 0x8010000D /* The specified smart card name is not recognized. */ + ErrSCardCannotDispose = 0x8010000E /* The system could not dispose of the media in the requested manner. */ + ErrSCardProtoMismatch = 0x8010000F /* The requested protocols are incompatible with the protocol currently in use with the smart card. */ + ErrSCardNotReady = 0x80100010 /* The reader or smart card is not ready to accept commands. */ + ErrSCardInvalidValue = 0x80100011 /* One or more of the supplied parameters values could not be properly interpreted. */ + ErrSCardSystemCancelled = 0x80100012 /* The action was cancelled by the system, presumably to log off or shut down. */ + ErrSCardCommError = 0x80100013 /* An internal communications error has been detected. */ + ErrScardUnknownError = 0x80100014 /* An internal error has been detected, but the source is unknown. */ + ErrSCardInvalidATR = 0x80100015 /* An ATR obtained from the registry is not a valid ATR string. */ + ErrSCardNotTransacted = 0x80100016 /* An attempt was made to end a non-existent transaction. */ + ErrSCardReaderUnavailable = 0x80100017 /* The specified reader is not currently available for use. */ + ErrSCardShutdown = 0x80100018 /* The operation has been aborted to allow the server application to exit. */ + ErrSCardPCITooSmall = 0x80100019 /* The PCI Receive buffer was too small. */ + ErrSCardReaderUnsupported = 0x8010001A /* The reader driver does not meet minimal requirements for support. */ + ErrSCardDuplicateReader = 0x8010001B /* The reader driver did not produce a unique reader name. */ + ErrSCardCardUnsupported = 0x8010001C /* The smart card does not meet minimal requirements for support. */ + ErrScardNoService = 0x8010001D /* The Smart card resource manager is not running. */ + ErrSCardServiceStopped = 0x8010001E /* The Smart card resource manager has shut down. */ + ErrSCardUnexpected = 0x8010001F /* An unexpected card error has occurred. */ + ErrSCardUnsupportedFeature = 0x8010001F /* This smart card does not support the requested feature. */ + ErrSCardICCInstallation = 0x80100020 /* No primary provider can be found for the smart card. */ + ErrSCardICCCreateOrder = 0x80100021 /* The requested order of object creation is not supported. */ + ErrSCardDirNotFound = 0x80100023 /* The identified directory does not exist in the smart card. */ + ErrSCardFileNotFound = 0x80100024 /* The identified file does not exist in the smart card. */ + ErrSCardNoDir = 0x80100025 /* The supplied path does not represent a smart card directory. */ + ErrSCardNoFile = 0x80100026 /* The supplied path does not represent a smart card file. */ + ErrScardNoAccess = 0x80100027 /* Access is denied to this file. */ + ErrSCardWriteTooMany = 0x80100028 /* The smart card does not have enough memory to store the information. */ + ErrSCardBadSeek = 0x80100029 /* There was an error trying to set the smart card file object pointer. */ + ErrSCardInvalidCHV = 0x8010002A /* The supplied PIN is incorrect. */ + ErrSCardUnknownResMNG = 0x8010002B /* An unrecognized error code was returned from a layered component. */ + ErrSCardNoSuchCertificate = 0x8010002C /* The requested certificate does not exist. */ + ErrSCardCertificateUnavailable = 0x8010002D /* The requested certificate could not be obtained. */ + ErrSCardNoReadersAvailable = 0x8010002E /* Cannot find a smart card reader. */ + ErrSCardCommDataLost = 0x8010002F /* A communications error with the smart card has been detected. Retry the operation. */ + ErrScardNoKeyContainer = 0x80100030 /* The requested key container does not exist on the smart card. */ + ErrSCardServerTooBusy = 0x80100031 /* The Smart Card Resource Manager is too busy to complete this operation. */ + ErrSCardUnsupportedCard = 0x80100065 /* The reader cannot communicate with the card, due to ATR string configuration conflicts. */ + ErrSCardUnresponsiveCard = 0x80100066 /* The smart card is not responding to a reset. */ + ErrSCardUnpoweredCard = 0x80100067 /* Power has been removed from the smart card, so that further communication is not possible. */ + ErrSCardResetCard = 0x80100068 /* The smart card has been reset, so any shared state information is invalid. */ + ErrSCardRemovedCard = 0x80100069 /* The smart card has been removed, so further communication is not possible. */ + ErrSCardSecurityViolation = 0x8010006A /* Access was denied because of a security violation. */ + ErrSCardWrongCHV = 0x8010006B /* The card cannot be accessed because the wrong PIN was presented. */ + ErrSCardCHVBlocked = 0x8010006C /* The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */ + ErrSCardEOF = 0x8010006D /* The end of the smart card file has been reached. */ + ErrSCardCancelledByUser = 0x8010006E /* The user pressed "Cancel" on a Smart Card Selection Dialog. */ + ErrSCardCardNotAuthenticated = 0x8010006F /* No PIN was presented to the smart card. */ +) + +// Code returns the error code, with an uint32 type to be used in PutUInt32 +func (code ErrorCode) Code() uint32 { + return uint32(code) +} + +func (code ErrorCode) Error() error { + switch code { + case SCardSuccess: + return fmt.Errorf("Command successful") + + case ErrSCardInternal: + return fmt.Errorf("Internal error") + + case ErrSCardCancelled: + return fmt.Errorf("Command cancelled") + + case ErrSCardInvalidHandle: + return fmt.Errorf("Invalid handle") + + case ErrSCardInvalidParameter: + return fmt.Errorf("Invalid parameter given") + + case ErrSCardInvalidTarget: + return fmt.Errorf("Invalid target given") + + case ErrSCardNoMemory: + return fmt.Errorf("Not enough memory") + + case ErrSCardWaitedTooLong: + return fmt.Errorf("Waited too long") + + case ErrSCardInsufficientBuffer: + return fmt.Errorf("Insufficient buffer") + + case ErrScardUnknownReader: + return fmt.Errorf("Unknown reader specified") + + case ErrSCardTimeout: + return fmt.Errorf("Command timeout") + + case ErrSCardSharingViolation: + return fmt.Errorf("Sharing violation") + + case ErrSCardNoSmartCard: + return fmt.Errorf("No smart card inserted") + + case ErrSCardUnknownCard: + return fmt.Errorf("Unknown card") + + case ErrSCardCannotDispose: + return fmt.Errorf("Cannot dispose handle") + + case ErrSCardProtoMismatch: + return fmt.Errorf("Card protocol mismatch") + + case ErrSCardNotReady: + return fmt.Errorf("Subsystem not ready") + + case ErrSCardInvalidValue: + return fmt.Errorf("Invalid value given") + + case ErrSCardSystemCancelled: + return fmt.Errorf("System cancelled") + + case ErrSCardCommError: + return fmt.Errorf("RPC transport error") + + case ErrScardUnknownError: + return fmt.Errorf("Unknown error") + + case ErrSCardInvalidATR: + return fmt.Errorf("Invalid ATR") + + case ErrSCardNotTransacted: + return fmt.Errorf("Transaction failed") + + case ErrSCardReaderUnavailable: + return fmt.Errorf("Reader is unavailable") + + /* case SCARD_P_SHUTDOWN: */ + case ErrSCardPCITooSmall: + return fmt.Errorf("PCI struct too small") + + case ErrSCardReaderUnsupported: + return fmt.Errorf("Reader is unsupported") + + case ErrSCardDuplicateReader: + return fmt.Errorf("Reader already exists") + + case ErrSCardCardUnsupported: + return fmt.Errorf("Card is unsupported") + + case ErrScardNoService: + return fmt.Errorf("Service not available") + + case ErrSCardServiceStopped: + return fmt.Errorf("Service was stopped") + + /* case SCARD_E_UNEXPECTED: */ + /* case SCARD_E_ICC_CREATEORDER: */ + /* case SCARD_E_UNSUPPORTED_FEATURE: */ + /* case SCARD_E_DIR_NOT_FOUND: */ + /* case SCARD_E_NO_DIR: */ + /* case SCARD_E_NO_FILE: */ + /* case SCARD_E_NO_ACCESS: */ + /* case SCARD_E_WRITE_TOO_MANY: */ + /* case SCARD_E_BAD_SEEK: */ + /* case SCARD_E_INVALID_CHV: */ + /* case SCARD_E_UNKNOWN_RES_MNG: */ + /* case SCARD_E_NO_SUCH_CERTIFICATE: */ + /* case SCARD_E_CERTIFICATE_UNAVAILABLE: */ + case ErrSCardNoReadersAvailable: + return fmt.Errorf("Cannot find a smart card reader") + + /* case SCARD_E_COMM_DATA_LOST: */ + /* case SCARD_E_NO_KEY_CONTAINER: */ + /* case SCARD_E_SERVER_TOO_BUSY: */ + case ErrSCardUnsupportedCard: + return fmt.Errorf("Card is not supported") + + case ErrSCardUnresponsiveCard: + return fmt.Errorf("Card is unresponsive") + + case ErrSCardUnpoweredCard: + return fmt.Errorf("Card is unpowered") + + case ErrSCardResetCard: + return fmt.Errorf("Card was reset") + + case ErrSCardRemovedCard: + return fmt.Errorf("Card was removed") + + /* case SCARD_W_SECURITY_VIOLATION: */ + /* case SCARD_W_WRONG_CHV: */ + /* case SCARD_W_CHV_BLOCKED: */ + /* case SCARD_W_EOF: */ + /* case SCARD_W_CANCELLED_BY_USER: */ + /* case SCARD_W_CARD_NOT_AUTHENTICATED: */ + + case ErrSCardUnsupportedFeature: + return fmt.Errorf("Feature not supported") + + default: + return fmt.Errorf("unknown error: %08x", code) + } +} diff --git a/vendor/github.com/gballet/go-libpcsclite/go.mod b/vendor/github.com/gballet/go-libpcsclite/go.mod new file mode 100644 index 000000000..e97f46b7f --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/go.mod @@ -0,0 +1 @@ +module github.com/gballet/go-libpcsclite diff --git a/vendor/github.com/gballet/go-libpcsclite/msg.go b/vendor/github.com/gballet/go-libpcsclite/msg.go new file mode 100644 index 000000000..1377082b1 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/msg.go @@ -0,0 +1,82 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package pcsc + +import ( + "encoding/binary" + "net" +) + +/** + * @brief Wrapper for the MessageSend() function. + * + * Called by clients to send messages to the server. + * The parameters \p command and \p data are set in the \c sharedSegmentMsg + * struct in order to be sent. + * + * @param[in] command Command to be sent. + * @param[in] dwClientID Client socket handle. + * @param[in] size Size of the message (\p data). + * @param[in] data_void Data to be sent. + * + * @return Same error codes as MessageSend(). + */ +func messageSendWithHeader(command uint32, conn net.Conn, data []byte) error { + /* Translate header into bytes */ + msgData := make([]byte, 8+len(data)) + binary.LittleEndian.PutUint32(msgData[4:], command) + binary.LittleEndian.PutUint32(msgData, uint32(len(data))) + + /* Copy payload */ + copy(msgData[8:], data) + + _, err := conn.Write(msgData) + return err +} + +// clientSetupSession prepares a communication channel for the client to talk to the server. +// This is called by the application to create a socket for local IPC with the +// server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME. +/* + * @param[out] pdwClientID Client Connection ID. + * + * @retval 0 Success. + * @retval -1 Can not create the socket. + * @retval -1 The socket can not open a connection. + * @retval -1 Can not set the socket to non-blocking. + */ +func clientSetupSession(daemonPath string) (net.Conn, error) { + path := PCSCDSockName + if len(daemonPath) > 0 { + path = daemonPath + } + return net.Dial("unix", path) +} diff --git a/vendor/github.com/gballet/go-libpcsclite/winscard.go b/vendor/github.com/gballet/go-libpcsclite/winscard.go new file mode 100644 index 000000000..b916db162 --- /dev/null +++ b/vendor/github.com/gballet/go-libpcsclite/winscard.go @@ -0,0 +1,402 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, Guillaume Ballet +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package pcsc + +import ( + "encoding/binary" + "fmt" + "net" + "sync" + "unsafe" +) + +// Client contains all the information needed to establish +// and maintain a connection to the deamon/card. +type Client struct { + conn net.Conn + + minor uint32 + major uint32 + + ctx uint32 + + mutex sync.Mutex + + readerStateDescriptors [MaxReaderStateDescriptors]ReaderState +} + +// EstablishContext asks the PCSC daemon to create a context +// handle for further communication with connected cards and +// readers. +func EstablishContext(path string, scope uint32) (*Client, error) { + client := &Client{} + + conn, err := clientSetupSession(path) + if err != nil { + return nil, err + } + client.conn = conn + + payload := make([]byte, 12) + response := make([]byte, 12) + + var code uint32 + var minor uint32 + for minor = ProtocolVersionMinor; minor <= ProtocolVersionMinor+1; minor++ { + /* Exchange version information */ + binary.LittleEndian.PutUint32(payload, ProtocolVersionMajor) + binary.LittleEndian.PutUint32(payload[4:], minor) + binary.LittleEndian.PutUint32(payload[8:], SCardSuccess.Code()) + err = messageSendWithHeader(CommandVersion, conn, payload) + if err != nil { + return nil, err + } + n, err := conn.Read(response) + if err != nil { + return nil, err + } + if n != len(response) { + return nil, fmt.Errorf("invalid response length: expected %d, got %d", len(response), n) + } + code = binary.LittleEndian.Uint32(response[8:]) + if code != SCardSuccess.Code() { + continue + } + client.major = binary.LittleEndian.Uint32(response) + client.minor = binary.LittleEndian.Uint32(response[4:]) + if client.major != ProtocolVersionMajor || client.minor != minor { + continue + } + break + } + + if code != SCardSuccess.Code() { + return nil, fmt.Errorf("invalid response code: expected %d, got %d (%v)", SCardSuccess, code, ErrorCode(code).Error()) + } + if client.major != ProtocolVersionMajor || (client.minor != minor && client.minor+1 != minor) { + return nil, fmt.Errorf("invalid version found: expected %d.%d, got %d.%d", ProtocolVersionMajor, ProtocolVersionMinor, client.major, client.minor) + } + + /* Establish the context proper */ + binary.LittleEndian.PutUint32(payload, scope) + binary.LittleEndian.PutUint32(payload[4:], 0) + binary.LittleEndian.PutUint32(payload[8:], SCardSuccess.Code()) + err = messageSendWithHeader(SCardEstablishContext, conn, payload) + if err != nil { + return nil, err + } + response = make([]byte, 12) + n, err := conn.Read(response) + if err != nil { + return nil, err + } + if n != len(response) { + return nil, fmt.Errorf("invalid response length: expected %d, got %d", len(response), n) + } + code = binary.LittleEndian.Uint32(response[8:]) + if code != SCardSuccess.Code() { + return nil, fmt.Errorf("invalid response code: expected %d, got %d (%v)", SCardSuccess, code, ErrorCode(code).Error()) + } + client.ctx = binary.LittleEndian.Uint32(response[4:]) + + return client, nil +} + +// ReleaseContext tells the daemon that the client will no longer +// need the context. +func (client *Client) ReleaseContext() error { + client.mutex.Lock() + defer client.mutex.Unlock() + + data := [8]byte{} + binary.LittleEndian.PutUint32(data[:], client.ctx) + binary.LittleEndian.PutUint32(data[4:], SCardSuccess.Code()) + err := messageSendWithHeader(SCardReleaseContext, client.conn, data[:]) + if err != nil { + return err + } + total := 0 + for total < len(data) { + n, err := client.conn.Read(data[total:]) + if err != nil { + return err + } + total += n + } + code := binary.LittleEndian.Uint32(data[4:]) + if code != SCardSuccess.Code() { + return fmt.Errorf("invalid return code: %x, %v", code, ErrorCode(code).Error()) + } + + return nil +} + +// Constants related to the reader state structure +const ( + ReaderStateNameLength = 128 + ReaderStateMaxAtrSizeLength = 33 + // NOTE: ATR is 32-byte aligned in the C version, which means it's + // actually 36 byte long and not 33. + ReaderStateDescriptorLength = ReaderStateNameLength + ReaderStateMaxAtrSizeLength + 5*4 + 3 + + MaxReaderStateDescriptors = 16 +) + +// ReaderState represent the state of a single reader, as reported +// by the PCSC daemon. +type ReaderState struct { + Name string /* reader name */ + eventCounter uint32 /* number of card events */ + readerState uint32 /* SCARD_* bit field */ + readerSharing uint32 /* PCSCLITE_SHARING_* sharing status */ + + cardAtr [ReaderStateMaxAtrSizeLength]byte /* ATR */ + cardAtrLength uint32 /* ATR length */ + cardProtocol uint32 /* SCARD_PROTOCOL_* value */ +} + +func getReaderState(data []byte) (ReaderState, error) { + ret := ReaderState{} + if len(data) < ReaderStateDescriptorLength { + return ret, fmt.Errorf("could not unmarshall data of length %d < %d", len(data), ReaderStateDescriptorLength) + } + + ret.Name = string(data[:ReaderStateNameLength]) + ret.eventCounter = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.eventCounter):]) + ret.readerState = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.readerState):]) + ret.readerSharing = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.readerSharing):]) + copy(ret.cardAtr[:], data[unsafe.Offsetof(ret.cardAtr):unsafe.Offsetof(ret.cardAtr)+ReaderStateMaxAtrSizeLength]) + ret.cardAtrLength = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.cardAtrLength):]) + ret.cardProtocol = binary.LittleEndian.Uint32(data[unsafe.Offsetof(ret.cardProtocol):]) + + return ret, nil +} + +// ListReaders gets the list of readers from the daemon +func (client *Client) ListReaders() ([]string, error) { + client.mutex.Lock() + defer client.mutex.Unlock() + + err := messageSendWithHeader(CommandGetReaderState, client.conn, []byte{}) + if err != nil { + return nil, err + } + response := make([]byte, ReaderStateDescriptorLength*MaxReaderStateDescriptors) + total := 0 + for total < len(response) { + n, err := client.conn.Read(response[total:]) + if err != nil { + return nil, err + } + total += n + } + + var names []string + for i := range client.readerStateDescriptors { + desc, err := getReaderState(response[i*ReaderStateDescriptorLength:]) + if err != nil { + return nil, err + } + client.readerStateDescriptors[i] = desc + if desc.Name[0] == 0 { + break + } + names = append(names, desc.Name) + } + + return names, nil +} + +// Offsets into the Connect request/response packet +const ( + SCardConnectReaderNameOffset = 4 + SCardConnectShareModeOffset = SCardConnectReaderNameOffset + ReaderStateNameLength + SCardConnectPreferredProtocolOffset = SCardConnectShareModeOffset + 4 + SCardConnectReturnValueOffset = SCardConnectPreferredProtocolOffset + 12 +) + +// Card represents the connection to a card +type Card struct { + handle uint32 + activeProto uint32 + client *Client +} + +// Connect asks the daemon to connect to the card +func (client *Client) Connect(name string, shareMode uint32, preferredProtocol uint32) (*Card, error) { + client.mutex.Lock() + defer client.mutex.Unlock() + + request := make([]byte, ReaderStateNameLength+4*6) + binary.LittleEndian.PutUint32(request, client.ctx) + copy(request[SCardConnectReaderNameOffset:], []byte(name)) + binary.LittleEndian.PutUint32(request[SCardConnectShareModeOffset:], shareMode) + binary.LittleEndian.PutUint32(request[SCardConnectPreferredProtocolOffset:], preferredProtocol) + binary.LittleEndian.PutUint32(request[SCardConnectReturnValueOffset:], SCardSuccess.Code()) + + err := messageSendWithHeader(SCardConnect, client.conn, request) + if err != nil { + return nil, err + } + response := make([]byte, ReaderStateNameLength+4*6) + total := 0 + for total < len(response) { + n, err := client.conn.Read(response[total:]) + if err != nil { + return nil, err + } + // fmt.Println("total, n", total, n, response) + total += n + } + code := binary.LittleEndian.Uint32(response[148:]) + if code != SCardSuccess.Code() { + return nil, fmt.Errorf("invalid return code: %x (%v)", code, ErrorCode(code).Error()) + } + handle := binary.LittleEndian.Uint32(response[140:]) + active := binary.LittleEndian.Uint32(response[SCardConnectPreferredProtocolOffset:]) + + return &Card{handle: handle, activeProto: active, client: client}, nil +} + +/** +* @brief contained in \ref SCARD_TRANSMIT Messages. +* +* These data are passed throw the field \c sharedSegmentMsg.data. + */ +type transmit struct { + hCard uint32 + ioSendPciProtocol uint32 + ioSendPciLength uint32 + cbSendLength uint32 + ioRecvPciProtocol uint32 + ioRecvPciLength uint32 + pcbRecvLength uint32 + rv uint32 +} + +// SCardIoRequest contains the info needed for performing an IO request +type SCardIoRequest struct { + proto uint32 + length uint32 +} + +const ( + TransmitRequestLength = 32 +) + +// Transmit sends request data to a card and returns the response +func (card *Card) Transmit(adpu []byte) ([]byte, *SCardIoRequest, error) { + card.client.mutex.Lock() + defer card.client.mutex.Unlock() + + request := [TransmitRequestLength]byte{} + binary.LittleEndian.PutUint32(request[:], card.handle) + binary.LittleEndian.PutUint32(request[4:] /*card.activeProto*/, 2) + binary.LittleEndian.PutUint32(request[8:], 8) + binary.LittleEndian.PutUint32(request[12:], uint32(len(adpu))) + binary.LittleEndian.PutUint32(request[16:], 0) + binary.LittleEndian.PutUint32(request[20:], 0) + binary.LittleEndian.PutUint32(request[24:], 0x10000) + binary.LittleEndian.PutUint32(request[28:], SCardSuccess.Code()) + err := messageSendWithHeader(SCardTransmit, card.client.conn, request[:]) + if err != nil { + return nil, nil, err + } + // Add the ADPU payload after the transmit descriptor + n, err := card.client.conn.Write(adpu) + if err != nil { + return nil, nil, err + } + if n != len(adpu) { + return nil, nil, fmt.Errorf("Invalid number of bytes written: expected %d, got %d", len(adpu), n) + } + response := [TransmitRequestLength]byte{} + total := 0 + for total < len(response) { + n, err = card.client.conn.Read(response[total:]) + if err != nil { + return nil, nil, err + } + total += n + } + + code := binary.LittleEndian.Uint32(response[28:]) + if code != SCardSuccess.Code() { + return nil, nil, fmt.Errorf("invalid return code: %x (%v)", code, ErrorCode(code).Error()) + } + + // Recover the response data + recvProto := binary.LittleEndian.Uint32(response[16:]) + recvLength := binary.LittleEndian.Uint32(response[20:]) + recv := &SCardIoRequest{proto: recvProto, length: recvLength} + recvLength = binary.LittleEndian.Uint32(response[24:]) + recvData := make([]byte, recvLength) + total = 0 + for uint32(total) < recvLength { + n, err := card.client.conn.Read(recvData[total:]) + if err != nil { + return nil, nil, err + } + total += n + } + + return recvData, recv, nil +} + +// Disconnect tells the PCSC daemon that the client is no longer +// interested in communicating with the card. +func (card *Card) Disconnect(disposition uint32) error { + card.client.mutex.Lock() + defer card.client.mutex.Unlock() + + data := [12]byte{} + binary.LittleEndian.PutUint32(data[:], card.handle) + binary.LittleEndian.PutUint32(data[4:], disposition) + binary.LittleEndian.PutUint32(data[8:], SCardSuccess.Code()) + err := messageSendWithHeader(SCardDisConnect, card.client.conn, data[:]) + if err != nil { + return err + } + total := 0 + for total < len(data) { + n, err := card.client.conn.Read(data[total:]) + if err != nil { + return err + } + total += n + } + code := binary.LittleEndian.Uint32(data[8:]) + if code != SCardSuccess.Code() { + return fmt.Errorf("invalid return code: %x (%v)", code, ErrorCode(code).Error()) + } + + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/.travis.yml b/vendor/github.com/go-ole/go-ole/.travis.yml new file mode 100644 index 000000000..0c2c02bdf --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/.travis.yml @@ -0,0 +1,9 @@ +language: go +sudo: false + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - tip diff --git a/vendor/github.com/go-ole/go-ole/ChangeLog.md b/vendor/github.com/go-ole/go-ole/ChangeLog.md new file mode 100644 index 000000000..4ba6a8c64 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ChangeLog.md @@ -0,0 +1,49 @@ +# Version 1.x.x + +* **Add more test cases and reference new test COM server project.** (Placeholder for future additions) + +# Version 1.2.0-alphaX + +**Minimum supported version is now Go 1.4. Go 1.1 support is deprecated, but should still build.** + + * Added CI configuration for Travis-CI and AppVeyor. + * Added test InterfaceID and ClassID for the COM Test Server project. + * Added more inline documentation (#83). + * Added IEnumVARIANT implementation (#88). + * Added IEnumVARIANT test cases (#99, #100, #101). + * Added support for retrieving `time.Time` from VARIANT (#92). + * Added test case for IUnknown (#64). + * Added test case for IDispatch (#64). + * Added test cases for scalar variants (#64, #76). + +# Version 1.1.1 + + * Fixes for Linux build. + * Fixes for Windows build. + +# Version 1.1.0 + +The change to provide building on all platforms is a new feature. The increase in minor version reflects that and allows those who wish to stay on 1.0.x to continue to do so. Support for 1.0.x will be limited to bug fixes. + + * Move GUID out of variables.go into its own file to make new documentation available. + * Move OleError out of ole.go into its own file to make new documentation available. + * Add documentation to utility functions. + * Add documentation to variant receiver functions. + * Add documentation to ole structures. + * Make variant available to other systems outside of Windows. + * Make OLE structures available to other systems outside of Windows. + +## New Features + + * Library should now be built on all platforms supported by Go. Library will NOOP on any platform that is not Windows. + * More functions are now documented and available on godoc.org. + +# Version 1.0.1 + + 1. Fix package references from repository location change. + +# Version 1.0.0 + +This version is stable enough for use. The COM API is still incomplete, but provides enough functionality for accessing COM servers using IDispatch interface. + +There is no changelog for this version. Check commits for history. diff --git a/vendor/github.com/go-ole/go-ole/LICENSE b/vendor/github.com/go-ole/go-ole/LICENSE new file mode 100644 index 000000000..623ec06f9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2013-2017 Yasuhiro Matsumoto, + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-ole/go-ole/README.md b/vendor/github.com/go-ole/go-ole/README.md new file mode 100644 index 000000000..0ea9db33c --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/README.md @@ -0,0 +1,46 @@ +#Go OLE + +[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28) +[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole) +[![GoDoc](https://godoc.org/github.com/go-ole/go-ole?status.svg)](https://godoc.org/github.com/go-ole/go-ole) + +Go bindings for Windows COM using shared libraries instead of cgo. + +By Yasuhiro Matsumoto. + +## Install + +To experiment with go-ole, you can just compile and run the example program: + +``` +go get github.com/go-ole/go-ole +cd /path/to/go-ole/ +go test + +cd /path/to/go-ole/example/excel +go run excel.go +``` + +## Continuous Integration + +Continuous integration configuration has been added for both Travis-CI and AppVeyor. You will have to add these to your own account for your fork in order for it to run. + +**Travis-CI** + +Travis-CI was added to check builds on Linux to ensure that `go get` works when cross building. Currently, Travis-CI is not used to test cross-building, but this may be changed in the future. It is also not currently possible to test the library on Linux, since COM API is specific to Windows and it is not currently possible to run a COM server on Linux or even connect to a remote COM server. + +**AppVeyor** + +AppVeyor is used to build on Windows using the (in-development) test COM server. It is currently only used to test the build and ensure that the code works on Windows. It will be used to register a COM server and then run the test cases based on the test COM server. + +The tests currently do run and do pass and this should be maintained with commits. + +##Versioning + +Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch. + +This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed. + +##LICENSE + +Under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml new file mode 100644 index 000000000..0d557ac2f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/appveyor.yml @@ -0,0 +1,54 @@ +# Notes: +# - Minimal appveyor.yml file is an empty file. All sections are optional. +# - Indent each level of configuration with 2 spaces. Do not use tabs! +# - All section names are case-sensitive. +# - Section names should be unique on each level. + +version: "1.3.0.{build}-alpha-{branch}" + +os: Windows Server 2012 R2 + +branches: + only: + - master + - v1.2 + - v1.1 + - v1.0 + +skip_tags: true + +clone_folder: c:\gopath\src\github.com\go-ole\go-ole + +environment: + GOPATH: c:\gopath + matrix: + - GOARCH: amd64 + GOVERSION: 1.5 + GOROOT: c:\go + DOWNLOADPLATFORM: "x64" + +install: + - choco install mingw + - SET PATH=c:\tools\mingw64\bin;%PATH% + # - Download COM Server + - ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip" + - 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL + - c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat + # - set + - go version + - go env + - go get -u golang.org/x/tools/cmd/cover + - go get -u golang.org/x/tools/cmd/godoc + - go get -u golang.org/x/tools/cmd/stringer + +build_script: + - cd c:\gopath\src\github.com\go-ole\go-ole + - go get -v -t ./... + - go build + - go test -v -cover ./... + +# disable automatic tests +test: off + +# disable deployment +deploy: off diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go new file mode 100644 index 000000000..75ebbf13f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com.go @@ -0,0 +1,329 @@ +// +build windows + +package ole + +import ( + "errors" + "syscall" + "time" + "unicode/utf16" + "unsafe" +) + +var ( + procCoInitialize, _ = modole32.FindProc("CoInitialize") + procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx") + procCoUninitialize, _ = modole32.FindProc("CoUninitialize") + procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance") + procCoTaskMemFree, _ = modole32.FindProc("CoTaskMemFree") + procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID") + procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString") + procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID") + procStringFromIID, _ = modole32.FindProc("StringFromIID") + procIIDFromString, _ = modole32.FindProc("IIDFromString") + procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID") + procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory") + procVariantInit, _ = modoleaut32.FindProc("VariantInit") + procVariantClear, _ = modoleaut32.FindProc("VariantClear") + procVariantTimeToSystemTime, _ = modoleaut32.FindProc("VariantTimeToSystemTime") + procSysAllocString, _ = modoleaut32.FindProc("SysAllocString") + procSysAllocStringLen, _ = modoleaut32.FindProc("SysAllocStringLen") + procSysFreeString, _ = modoleaut32.FindProc("SysFreeString") + procSysStringLen, _ = modoleaut32.FindProc("SysStringLen") + procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo") + procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch") + procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject") + + procGetMessageW, _ = moduser32.FindProc("GetMessageW") + procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW") +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx + // Suggests that no value should be passed to CoInitialized. + // Could just be Call() since the parameter is optional. <-- Needs testing to be sure. + hr, _, _ := procCoInitialize.Call(uintptr(0)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx + // Suggests that the first parameter is not only optional but should always be NULL. + hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) (err error) { + // p is ignored and won't be used. + // Avoid any variable not used errors. + p = uintptr(0) + return coInitialize() +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) (err error) { + // Avoid any variable not used errors. + p = uintptr(0) + return coInitializeEx(coinit) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() { + procCoUninitialize.Call() +} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) { + procCoTaskMemFree.Call(memptr) +} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (clsid *GUID, err error) { + var guid GUID + lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) + hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procCoCreateInstance.Call( + uintptr(unsafe.Pointer(clsid)), + 0, + CLSCTX_SERVER, + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procGetActiveObject.Call( + uintptr(unsafe.Pointer(clsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) (err error) { + hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) (err error) { + hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) (ss *int16) { + pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) (ss *int16) { + utf16 := utf16.Encode([]rune(v + "\x00")) + ptr := &utf16[0] + + pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1)) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) (err error) { + hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) + return uint32(l) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) { + hr, _, _ := procCreateStdDispatch.Call( + uintptr(unsafe.Pointer(unk)), + v, + uintptr(unsafe.Pointer(ptinfo)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) { + hr, _, _ := procCreateDispTypeInfo.Call( + uintptr(unsafe.Pointer(idata)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&pptinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) { + procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length)) +} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() (lcid uint32) { + ret, _, _ := procGetUserDefaultLCID.Call() + lcid = uint32(ret) + return +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) { + r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax)) + ret = int32(r0) + return +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) (ret int32) { + r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg))) + ret = int32(r0) + return +} + +// GetVariantDate converts COM Variant Time value to Go time.Time. +func GetVariantDate(value float64) (time.Time, error) { + var st syscall.Systemtime + r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st))) + if r != 0 { + return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil + } + return time.Now(), errors.New("Could not convert to time, passing current time.") +} diff --git a/vendor/github.com/go-ole/go-ole/com_func.go b/vendor/github.com/go-ole/go-ole/com_func.go new file mode 100644 index 000000000..425aad323 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com_func.go @@ -0,0 +1,174 @@ +// +build !windows + +package ole + +import ( + "time" + "unsafe" +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() error { + return NewError(E_NOTIMPL) +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) error { + return NewError(E_NOTIMPL) +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() {} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) {} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) *int16 { + u := int16(0) + return &u +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) *int16 { + u := int16(0) + return &u +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) error { + return NewError(E_NOTIMPL) +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + return uint32(0) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (*IDispatch, error) { + return nil, NewError(E_NOTIMPL) +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() uint32 { + return uint32(0) +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (int32, error) { + return int32(0), NewError(E_NOTIMPL) +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) int32 { + return int32(0) +} + +func GetVariantDate(value float64) (time.Time, error) { + return time.Now(), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/connect.go b/vendor/github.com/go-ole/go-ole/connect.go new file mode 100644 index 000000000..b2ac2ec67 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/connect.go @@ -0,0 +1,192 @@ +package ole + +// Connection contains IUnknown for fluent interface interaction. +// +// Deprecated. Use oleutil package instead. +type Connection struct { + Object *IUnknown // Access COM +} + +// Initialize COM. +func (*Connection) Initialize() (err error) { + return coInitialize() +} + +// Uninitialize COM. +func (*Connection) Uninitialize() { + CoUninitialize() +} + +// Create IUnknown object based first on ProgId and then from String. +func (c *Connection) Create(progId string) (err error) { + var clsid *GUID + clsid, err = CLSIDFromProgID(progId) + if err != nil { + clsid, err = CLSIDFromString(progId) + if err != nil { + return + } + } + + unknown, err := CreateInstance(clsid, IID_IUnknown) + if err != nil { + return + } + c.Object = unknown + + return +} + +// Release IUnknown object. +func (c *Connection) Release() { + c.Object.Release() +} + +// Load COM object from list of programIDs or strings. +func (c *Connection) Load(names ...string) (errors []error) { + var tempErrors []error = make([]error, len(names)) + var numErrors int = 0 + for _, name := range names { + err := c.Create(name) + if err != nil { + tempErrors = append(tempErrors, err) + numErrors += 1 + continue + } + break + } + + copy(errors, tempErrors[0:numErrors]) + return +} + +// Dispatch returns Dispatch object. +func (c *Connection) Dispatch() (object *Dispatch, err error) { + dispatch, err := c.Object.QueryInterface(IID_IDispatch) + if err != nil { + return + } + object = &Dispatch{dispatch} + return +} + +// Dispatch stores IDispatch object. +type Dispatch struct { + Object *IDispatch // Dispatch object. +} + +// Call method on IDispatch with parameters. +func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(method) + if err != nil { + return + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + return +} + +// MustCall method on IDispatch with parameters. +func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(method) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + if err != nil { + panic(err) + } + + return +} + +// Get property on IDispatch with parameters. +func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + return +} + +// MustGet property on IDispatch with parameters. +func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + if err != nil { + panic(err) + } + return +} + +// Set property on IDispatch with parameters. +func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + return +} + +// MustSet property on IDispatch with parameters. +func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + if err != nil { + panic(err) + } + return +} + +// GetId retrieves ID of name on IDispatch. +func (d *Dispatch) GetId(name string) (id int32, err error) { + var dispid []int32 + dispid, err = d.Object.GetIDsOfName([]string{name}) + if err != nil { + return + } + id = dispid[0] + return +} + +// GetIds retrieves all IDs of names on IDispatch. +func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) { + dispid, err = d.Object.GetIDsOfName(names) + return +} + +// Invoke IDispatch on DisplayID of dispatch type with parameters. +// +// There have been problems where if send cascading params..., it would error +// out because the parameters would be empty. +func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) { + if len(params) < 1 { + result, err = d.Object.Invoke(id, dispatch) + } else { + result, err = d.Object.Invoke(id, dispatch, params...) + } + return +} + +// Release IDispatch object. +func (d *Dispatch) Release() { + d.Object.Release() +} + +// Connect initializes COM and attempts to load IUnknown based on given names. +func Connect(names ...string) (connection *Connection) { + connection.Initialize() + connection.Load(names...) + return +} diff --git a/vendor/github.com/go-ole/go-ole/constants.go b/vendor/github.com/go-ole/go-ole/constants.go new file mode 100644 index 000000000..fd0c6d74b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/constants.go @@ -0,0 +1,153 @@ +package ole + +const ( + CLSCTX_INPROC_SERVER = 1 + CLSCTX_INPROC_HANDLER = 2 + CLSCTX_LOCAL_SERVER = 4 + CLSCTX_INPROC_SERVER16 = 8 + CLSCTX_REMOTE_SERVER = 16 + CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER + CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER + CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER +) + +const ( + COINIT_APARTMENTTHREADED = 0x2 + COINIT_MULTITHREADED = 0x0 + COINIT_DISABLE_OLE1DDE = 0x4 + COINIT_SPEED_OVER_MEMORY = 0x8 +) + +const ( + DISPATCH_METHOD = 1 + DISPATCH_PROPERTYGET = 2 + DISPATCH_PROPERTYPUT = 4 + DISPATCH_PROPERTYPUTREF = 8 +) + +const ( + S_OK = 0x00000000 + E_UNEXPECTED = 0x8000FFFF + E_NOTIMPL = 0x80004001 + E_OUTOFMEMORY = 0x8007000E + E_INVALIDARG = 0x80070057 + E_NOINTERFACE = 0x80004002 + E_POINTER = 0x80004003 + E_HANDLE = 0x80070006 + E_ABORT = 0x80004004 + E_FAIL = 0x80004005 + E_ACCESSDENIED = 0x80070005 + E_PENDING = 0x8000000A + + CO_E_CLASSSTRING = 0x800401F3 +) + +const ( + CC_FASTCALL = iota + CC_CDECL + CC_MSCPASCAL + CC_PASCAL = CC_MSCPASCAL + CC_MACPASCAL + CC_STDCALL + CC_FPFASTCALL + CC_SYSCALL + CC_MPWCDECL + CC_MPWPASCAL + CC_MAX = CC_MPWPASCAL +) + +type VT uint16 + +const ( + VT_EMPTY VT = 0x0 + VT_NULL VT = 0x1 + VT_I2 VT = 0x2 + VT_I4 VT = 0x3 + VT_R4 VT = 0x4 + VT_R8 VT = 0x5 + VT_CY VT = 0x6 + VT_DATE VT = 0x7 + VT_BSTR VT = 0x8 + VT_DISPATCH VT = 0x9 + VT_ERROR VT = 0xa + VT_BOOL VT = 0xb + VT_VARIANT VT = 0xc + VT_UNKNOWN VT = 0xd + VT_DECIMAL VT = 0xe + VT_I1 VT = 0x10 + VT_UI1 VT = 0x11 + VT_UI2 VT = 0x12 + VT_UI4 VT = 0x13 + VT_I8 VT = 0x14 + VT_UI8 VT = 0x15 + VT_INT VT = 0x16 + VT_UINT VT = 0x17 + VT_VOID VT = 0x18 + VT_HRESULT VT = 0x19 + VT_PTR VT = 0x1a + VT_SAFEARRAY VT = 0x1b + VT_CARRAY VT = 0x1c + VT_USERDEFINED VT = 0x1d + VT_LPSTR VT = 0x1e + VT_LPWSTR VT = 0x1f + VT_RECORD VT = 0x24 + VT_INT_PTR VT = 0x25 + VT_UINT_PTR VT = 0x26 + VT_FILETIME VT = 0x40 + VT_BLOB VT = 0x41 + VT_STREAM VT = 0x42 + VT_STORAGE VT = 0x43 + VT_STREAMED_OBJECT VT = 0x44 + VT_STORED_OBJECT VT = 0x45 + VT_BLOB_OBJECT VT = 0x46 + VT_CF VT = 0x47 + VT_CLSID VT = 0x48 + VT_BSTR_BLOB VT = 0xfff + VT_VECTOR VT = 0x1000 + VT_ARRAY VT = 0x2000 + VT_BYREF VT = 0x4000 + VT_RESERVED VT = 0x8000 + VT_ILLEGAL VT = 0xffff + VT_ILLEGALMASKED VT = 0xfff + VT_TYPEMASK VT = 0xfff +) + +const ( + DISPID_UNKNOWN = -1 + DISPID_VALUE = 0 + DISPID_PROPERTYPUT = -3 + DISPID_NEWENUM = -4 + DISPID_EVALUATE = -5 + DISPID_CONSTRUCTOR = -6 + DISPID_DESTRUCTOR = -7 + DISPID_COLLECT = -8 +) + +const ( + TKIND_ENUM = 1 + TKIND_RECORD = 2 + TKIND_MODULE = 3 + TKIND_INTERFACE = 4 + TKIND_DISPATCH = 5 + TKIND_COCLASS = 6 + TKIND_ALIAS = 7 + TKIND_UNION = 8 + TKIND_MAX = 9 +) + +// Safe Array Feature Flags + +const ( + FADF_AUTO = 0x0001 + FADF_STATIC = 0x0002 + FADF_EMBEDDED = 0x0004 + FADF_FIXEDSIZE = 0x0010 + FADF_RECORD = 0x0020 + FADF_HAVEIID = 0x0040 + FADF_HAVEVARTYPE = 0x0080 + FADF_BSTR = 0x0100 + FADF_UNKNOWN = 0x0200 + FADF_DISPATCH = 0x0400 + FADF_VARIANT = 0x0800 + FADF_RESERVED = 0xF008 +) diff --git a/vendor/github.com/go-ole/go-ole/error.go b/vendor/github.com/go-ole/go-ole/error.go new file mode 100644 index 000000000..096b456d3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error.go @@ -0,0 +1,51 @@ +package ole + +// OleError stores COM errors. +type OleError struct { + hr uintptr + description string + subError error +} + +// NewError creates new error with HResult. +func NewError(hr uintptr) *OleError { + return &OleError{hr: hr} +} + +// NewErrorWithDescription creates new COM error with HResult and description. +func NewErrorWithDescription(hr uintptr, description string) *OleError { + return &OleError{hr: hr, description: description} +} + +// NewErrorWithSubError creates new COM error with parent error. +func NewErrorWithSubError(hr uintptr, description string, err error) *OleError { + return &OleError{hr: hr, description: description, subError: err} +} + +// Code is the HResult. +func (v *OleError) Code() uintptr { + return uintptr(v.hr) +} + +// String description, either manually set or format message with error code. +func (v *OleError) String() string { + if v.description != "" { + return errstr(int(v.hr)) + " (" + v.description + ")" + } + return errstr(int(v.hr)) +} + +// Error implements error interface. +func (v *OleError) Error() string { + return v.String() +} + +// Description retrieves error summary, if there is one. +func (v *OleError) Description() string { + return v.description +} + +// SubError returns parent error, if there is one. +func (v *OleError) SubError() error { + return v.subError +} diff --git a/vendor/github.com/go-ole/go-ole/error_func.go b/vendor/github.com/go-ole/go-ole/error_func.go new file mode 100644 index 000000000..8a2ffaa27 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_func.go @@ -0,0 +1,8 @@ +// +build !windows + +package ole + +// errstr converts error code to string. +func errstr(errno int) string { + return "" +} diff --git a/vendor/github.com/go-ole/go-ole/error_windows.go b/vendor/github.com/go-ole/go-ole/error_windows.go new file mode 100644 index 000000000..d0e8e6859 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_windows.go @@ -0,0 +1,24 @@ +// +build windows + +package ole + +import ( + "fmt" + "syscall" + "unicode/utf16" +) + +// errstr converts error code to string. +func errstr(errno int) string { + // ask windows for the remaining errors + var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS + b := make([]uint16, 300) + n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil) + if err != nil { + return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err) + } + // trim terminating \r and \n + for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { + } + return string(utf16.Decode(b[:n])) +} diff --git a/vendor/github.com/go-ole/go-ole/guid.go b/vendor/github.com/go-ole/go-ole/guid.go new file mode 100644 index 000000000..8d20f68fb --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/guid.go @@ -0,0 +1,284 @@ +package ole + +var ( + // IID_NULL is null Interface ID, used when no other Interface ID is known. + IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}") + + // IID_IUnknown is for IUnknown interfaces. + IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}") + + // IID_IDispatch is for IDispatch interfaces. + IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}") + + // IID_IEnumVariant is for IEnumVariant interfaces + IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}") + + // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces. + IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}") + + // IID_IConnectionPoint is for IConnectionPoint interfaces. + IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}") + + // IID_IInspectable is for IInspectable interfaces. + IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}") + + // IID_IProvideClassInfo is for IProvideClassInfo interfaces. + IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}") +) + +// These are for testing and not part of any library. +var ( + // IID_ICOMTestString is for ICOMTestString interfaces. + // + // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED} + IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}") + + // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces. + // + // {BEB06610-EB84-4155-AF58-E2BFF53680B4} + IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}") + + // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces. + // + // {DAA3F9FA-761E-4976-A860-8364CE55F6FC} + IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}") + + // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces. + // + // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0} + IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}") + + // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces. + // + // {8D437CBC-B3ED-485C-BC32-C336432A1623} + IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}") + + // IID_ICOMTestFloat is for ICOMTestFloat interfaces. + // + // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C} + IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}") + + // IID_ICOMTestDouble is for ICOMTestDouble interfaces. + // + // {BF908A81-8687-4E93-999F-D86FAB284BA0} + IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}") + + // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces. + // + // {D530E7A6-4EE8-40D1-8931-3D63B8605010} + IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}") + + // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces. + // + // {6485B1EF-D780-4834-A4FE-1EBB51746CA3} + IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}") + + // IID_ICOMTestTypes is for ICOMTestTypes interfaces. + // + // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0} + IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}") + + // CLSID_COMEchoTestObject is for COMEchoTestObject class. + // + // {3C24506A-AE9E-4D50-9157-EF317281F1B0} + CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}") + + // CLSID_COMTestScalarClass is for COMTestScalarClass class. + // + // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86} + CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}") +) + +const hextable = "0123456789ABCDEF" +const emptyGUID = "{00000000-0000-0000-0000-000000000000}" + +// GUID is Windows API specific GUID type. +// +// This exists to match Windows GUID type for direct passing for COM. +// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +// NewGUID converts the given string into a globally unique identifier that is +// compliant with the Windows API. +// +// The supplied string may be in any of these formats: +// +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// The conversion of the supplied string is not case-sensitive. +func NewGUID(guid string) *GUID { + d := []byte(guid) + var d1, d2, d3, d4a, d4b []byte + + switch len(d) { + case 38: + if d[0] != '{' || d[37] != '}' { + return nil + } + d = d[1:37] + fallthrough + case 36: + if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { + return nil + } + d1 = d[0:8] + d2 = d[9:13] + d3 = d[14:18] + d4a = d[19:23] + d4b = d[24:36] + case 32: + d1 = d[0:8] + d2 = d[8:12] + d3 = d[12:16] + d4a = d[16:20] + d4b = d[20:32] + default: + return nil + } + + var g GUID + var ok1, ok2, ok3, ok4 bool + g.Data1, ok1 = decodeHexUint32(d1) + g.Data2, ok2 = decodeHexUint16(d2) + g.Data3, ok3 = decodeHexUint16(d3) + g.Data4, ok4 = decodeHexByte64(d4a, d4b) + if ok1 && ok2 && ok3 && ok4 { + return &g + } + return nil +} + +func decodeHexUint32(src []byte) (value uint32, ok bool) { + var b1, b2, b3, b4 byte + var ok1, ok2, ok3, ok4 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + b3, ok3 = decodeHexByte(src[4], src[5]) + b4, ok4 = decodeHexByte(src[6], src[7]) + value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) + ok = ok1 && ok2 && ok3 && ok4 + return +} + +func decodeHexUint16(src []byte) (value uint16, ok bool) { + var b1, b2 byte + var ok1, ok2 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + value = (uint16(b1) << 8) | uint16(b2) + ok = ok1 && ok2 + return +} + +func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { + var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool + value[0], ok1 = decodeHexByte(s1[0], s1[1]) + value[1], ok2 = decodeHexByte(s1[2], s1[3]) + value[2], ok3 = decodeHexByte(s2[0], s2[1]) + value[3], ok4 = decodeHexByte(s2[2], s2[3]) + value[4], ok5 = decodeHexByte(s2[4], s2[5]) + value[5], ok6 = decodeHexByte(s2[6], s2[7]) + value[6], ok7 = decodeHexByte(s2[8], s2[9]) + value[7], ok8 = decodeHexByte(s2[10], s2[11]) + ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 + return +} + +func decodeHexByte(c1, c2 byte) (value byte, ok bool) { + var n1, n2 byte + var ok1, ok2 bool + n1, ok1 = decodeHexChar(c1) + n2, ok2 = decodeHexChar(c2) + value = (n1 << 4) | n2 + ok = ok1 && ok2 + return +} + +func decodeHexChar(c byte) (byte, bool) { + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + + return 0, false +} + +// String converts the GUID to string form. It will adhere to this pattern: +// +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// If the GUID is nil, the string representation of an empty GUID is returned: +// +// {00000000-0000-0000-0000-000000000000} +func (guid *GUID) String() string { + if guid == nil { + return emptyGUID + } + + var c [38]byte + c[0] = '{' + putUint32Hex(c[1:9], guid.Data1) + c[9] = '-' + putUint16Hex(c[10:14], guid.Data2) + c[14] = '-' + putUint16Hex(c[15:19], guid.Data3) + c[19] = '-' + putByteHex(c[20:24], guid.Data4[0:2]) + c[24] = '-' + putByteHex(c[25:37], guid.Data4[2:8]) + c[37] = '}' + return string(c[:]) +} + +func putUint32Hex(b []byte, v uint32) { + b[0] = hextable[byte(v>>24)>>4] + b[1] = hextable[byte(v>>24)&0x0f] + b[2] = hextable[byte(v>>16)>>4] + b[3] = hextable[byte(v>>16)&0x0f] + b[4] = hextable[byte(v>>8)>>4] + b[5] = hextable[byte(v>>8)&0x0f] + b[6] = hextable[byte(v)>>4] + b[7] = hextable[byte(v)&0x0f] +} + +func putUint16Hex(b []byte, v uint16) { + b[0] = hextable[byte(v>>8)>>4] + b[1] = hextable[byte(v>>8)&0x0f] + b[2] = hextable[byte(v)>>4] + b[3] = hextable[byte(v)&0x0f] +} + +func putByteHex(dst, src []byte) { + for i := 0; i < len(src); i++ { + dst[i*2] = hextable[src[i]>>4] + dst[i*2+1] = hextable[src[i]&0x0f] + } +} + +// IsEqualGUID compares two GUID. +// +// Not constant time comparison. +func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { + return guid1.Data1 == guid2.Data1 && + guid1.Data2 == guid2.Data2 && + guid1.Data3 == guid2.Data3 && + guid1.Data4[0] == guid2.Data4[0] && + guid1.Data4[1] == guid2.Data4[1] && + guid1.Data4[2] == guid2.Data4[2] && + guid1.Data4[3] == guid2.Data4[3] && + guid1.Data4[4] == guid2.Data4[4] && + guid1.Data4[5] == guid2.Data4[5] && + guid1.Data4[6] == guid2.Data4[6] && + guid1.Data4[7] == guid2.Data4[7] +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go new file mode 100644 index 000000000..9e6c49f41 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go @@ -0,0 +1,20 @@ +package ole + +import "unsafe" + +type IConnectionPoint struct { + IUnknown +} + +type IConnectionPointVtbl struct { + IUnknownVtbl + GetConnectionInterface uintptr + GetConnectionPointContainer uintptr + Advise uintptr + Unadvise uintptr + EnumConnections uintptr +} + +func (v *IConnectionPoint) VTable() *IConnectionPointVtbl { + return (*IConnectionPointVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go new file mode 100644 index 000000000..5414dc3cd --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go @@ -0,0 +1,21 @@ +// +build !windows + +package ole + +import "unsafe" + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + return int32(0) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go new file mode 100644 index 000000000..32bc18324 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go @@ -0,0 +1,43 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + // XXX: This doesn't look like it does what it's supposed to + return release((*IUnknown)(unsafe.Pointer(v))) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Advise, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(unknown)), + uintptr(unsafe.Pointer(&cookie))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Unadvise, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(cookie), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go new file mode 100644 index 000000000..165860d19 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go @@ -0,0 +1,17 @@ +package ole + +import "unsafe" + +type IConnectionPointContainer struct { + IUnknown +} + +type IConnectionPointContainerVtbl struct { + IUnknownVtbl + EnumConnectionPoints uintptr + FindConnectionPoint uintptr +} + +func (v *IConnectionPointContainer) VTable() *IConnectionPointContainerVtbl { + return (*IConnectionPointContainerVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go new file mode 100644 index 000000000..5dfa42aae --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go @@ -0,0 +1,11 @@ +// +build !windows + +package ole + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go new file mode 100644 index 000000000..ad30d79ef --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go @@ -0,0 +1,25 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().FindConnectionPoint, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(point))) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch.go b/vendor/github.com/go-ole/go-ole/idispatch.go new file mode 100644 index 000000000..d4af12409 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch.go @@ -0,0 +1,94 @@ +package ole + +import "unsafe" + +type IDispatch struct { + IUnknown +} + +type IDispatchVtbl struct { + IUnknownVtbl + GetTypeInfoCount uintptr + GetTypeInfo uintptr + GetIDsOfNames uintptr + Invoke uintptr +} + +func (v *IDispatch) VTable() *IDispatchVtbl { + return (*IDispatchVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) { + dispid, err = getIDsOfName(v, names) + return +} + +func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + result, err = invoke(v, dispid, dispatch, params...) + return +} + +func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) { + c, err = getTypeInfoCount(v) + return +} + +func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) { + tinfo, err = getTypeInfo(v) + return +} + +// GetSingleIDOfName is a helper that returns single display ID for IDispatch name. +// +// This replaces the common pattern of attempting to get a single name from the list of available +// IDs. It gives the first ID, if it is available. +func (v *IDispatch) GetSingleIDOfName(name string) (displayID int32, err error) { + var displayIDs []int32 + displayIDs, err = v.GetIDsOfName([]string{name}) + if err != nil { + return + } + displayID = displayIDs[0] + return +} + +// InvokeWithOptionalArgs accepts arguments as an array, works like Invoke. +// +// Accepts name and will attempt to retrieve Display ID to pass to Invoke. +// +// Passing params as an array is a workaround that could be fixed in later versions of Go that +// prevent passing empty params. During testing it was discovered that this is an acceptable way of +// getting around not being able to pass params normally. +func (v *IDispatch) InvokeWithOptionalArgs(name string, dispatch int16, params []interface{}) (result *VARIANT, err error) { + displayID, err := v.GetSingleIDOfName(name) + if err != nil { + return + } + + if len(params) < 1 { + result, err = v.Invoke(displayID, dispatch) + } else { + result, err = v.Invoke(displayID, dispatch, params...) + } + + return +} + +// CallMethod invokes named function with arguments on object. +func (v *IDispatch) CallMethod(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_METHOD, params) +} + +// GetProperty retrieves the property with the name with the ability to pass arguments. +// +// Most of the time you will not need to pass arguments as most objects do not allow for this +// feature. Or at least, should not allow for this feature. Some servers don't follow best practices +// and this is provided for those edge cases. +func (v *IDispatch) GetProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYGET, params) +} + +// PutProperty attempts to mutate a property in the object. +func (v *IDispatch) PutProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYPUT, params) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_func.go b/vendor/github.com/go-ole/go-ole/idispatch_func.go new file mode 100644 index 000000000..b8fbbe319 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func getIDsOfName(disp *IDispatch, names []string) ([]int32, error) { + return []int32{}, NewError(E_NOTIMPL) +} + +func getTypeInfoCount(disp *IDispatch) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func getTypeInfo(disp *IDispatch) (*ITypeInfo, error) { + return nil, NewError(E_NOTIMPL) +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go new file mode 100644 index 000000000..020e4f51b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_windows.go @@ -0,0 +1,197 @@ +// +build windows + +package ole + +import ( + "syscall" + "time" + "unsafe" +) + +func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) { + wnames := make([]*uint16, len(names)) + for i := 0; i < len(names); i++ { + wnames[i] = syscall.StringToUTF16Ptr(names[i]) + } + dispid = make([]int32, len(names)) + namelen := uint32(len(names)) + hr, _, _ := syscall.Syscall6( + disp.VTable().GetIDsOfNames, + 6, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(unsafe.Pointer(&wnames[0])), + uintptr(namelen), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&dispid[0]))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfoCount(disp *IDispatch) (c uint32, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfoCount, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&c)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfo, + 3, + uintptr(unsafe.Pointer(disp)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&tinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + var dispparams DISPPARAMS + + if dispatch&DISPATCH_PROPERTYPUT != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } else if dispatch&DISPATCH_PROPERTYPUTREF != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } + var vargs []VARIANT + if len(params) > 0 { + vargs = make([]VARIANT, len(params)) + for i, v := range params { + //n := len(params)-i-1 + n := len(params) - i - 1 + VariantInit(&vargs[n]) + switch vv := v.(type) { + case bool: + if vv { + vargs[n] = NewVariant(VT_BOOL, 0xffff) + } else { + vargs[n] = NewVariant(VT_BOOL, 0) + } + case *bool: + vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool))))) + case uint8: + vargs[n] = NewVariant(VT_I1, int64(v.(uint8))) + case *uint8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int8: + vargs[n] = NewVariant(VT_I1, int64(v.(int8))) + case *int8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int16: + vargs[n] = NewVariant(VT_I2, int64(v.(int16))) + case *int16: + vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16))))) + case uint16: + vargs[n] = NewVariant(VT_UI2, int64(v.(uint16))) + case *uint16: + vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16))))) + case int32: + vargs[n] = NewVariant(VT_I4, int64(v.(int32))) + case *int32: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32))))) + case uint32: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint32))) + case *uint32: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32))))) + case int64: + vargs[n] = NewVariant(VT_I8, int64(v.(int64))) + case *int64: + vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64))))) + case uint64: + vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64)))) + case *uint64: + vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64))))) + case int: + vargs[n] = NewVariant(VT_I4, int64(v.(int))) + case *int: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int))))) + case uint: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint))) + case *uint: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint))))) + case float32: + vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv))) + case *float32: + vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32))))) + case float64: + vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv))) + case *float64: + vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64))))) + case string: + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string)))))) + case *string: + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string))))) + case time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s))))) + case *time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s)))) + case *IDispatch: + vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))) + case **IDispatch: + vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))) + case nil: + vargs[n] = NewVariant(VT_NULL, 0) + case *VARIANT: + vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))) + case []byte: + safeByteArray := safeArrayFromByteSlice(v.([]byte)) + vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + case []string: + safeByteArray := safeArrayFromStringSlice(v.([]string)) + vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + default: + panic("unknown type") + } + } + dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0])) + dispparams.cArgs = uint32(len(params)) + } + + result = new(VARIANT) + var excepInfo EXCEPINFO + VariantInit(result) + hr, _, _ := syscall.Syscall9( + disp.VTable().Invoke, + 9, + uintptr(unsafe.Pointer(disp)), + uintptr(dispid), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(GetUserDefaultLCID()), + uintptr(dispatch), + uintptr(unsafe.Pointer(&dispparams)), + uintptr(unsafe.Pointer(result)), + uintptr(unsafe.Pointer(&excepInfo)), + 0) + if hr != 0 { + err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo) + } + for i, varg := range vargs { + n := len(params) - i - 1 + if varg.VT == VT_BSTR && varg.Val != 0 { + SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) + } + if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 { + *(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val)))) + } + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant.go b/vendor/github.com/go-ole/go-ole/ienumvariant.go new file mode 100644 index 000000000..243389754 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant.go @@ -0,0 +1,19 @@ +package ole + +import "unsafe" + +type IEnumVARIANT struct { + IUnknown +} + +type IEnumVARIANTVtbl struct { + IUnknownVtbl + Next uintptr + Skip uintptr + Reset uintptr + Clone uintptr +} + +func (v *IEnumVARIANT) VTable() *IEnumVARIANTVtbl { + return (*IEnumVARIANTVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go new file mode 100644 index 000000000..c14848199 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func (enum *IEnumVARIANT) Clone() (*IEnumVARIANT, error) { + return nil, NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Reset() error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Skip(celt uint) error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Next(celt uint) (VARIANT, uint, error) { + return NewVariant(VT_NULL, int64(0)), 0, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go new file mode 100644 index 000000000..4781f3b8b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go @@ -0,0 +1,63 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (enum *IEnumVARIANT) Clone() (cloned *IEnumVARIANT, err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Clone, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(unsafe.Pointer(&cloned)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Reset() (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Reset, + 1, + uintptr(unsafe.Pointer(enum)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Skip(celt uint) (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Skip, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Next(celt uint) (array VARIANT, length uint, err error) { + hr, _, _ := syscall.Syscall6( + enum.VTable().Next, + 4, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + uintptr(unsafe.Pointer(&array)), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable.go b/vendor/github.com/go-ole/go-ole/iinspectable.go new file mode 100644 index 000000000..f4a19e253 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable.go @@ -0,0 +1,18 @@ +package ole + +import "unsafe" + +type IInspectable struct { + IUnknown +} + +type IInspectableVtbl struct { + IUnknownVtbl + GetIIds uintptr + GetRuntimeClassName uintptr + GetTrustLevel uintptr +} + +func (v *IInspectable) VTable() *IInspectableVtbl { + return (*IInspectableVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_func.go b/vendor/github.com/go-ole/go-ole/iinspectable_func.go new file mode 100644 index 000000000..348829bf0 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_func.go @@ -0,0 +1,15 @@ +// +build !windows + +package ole + +func (v *IInspectable) GetIids() ([]*GUID, error) { + return []*GUID{}, NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetRuntimeClassName() (string, error) { + return "", NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetTrustLevel() (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go new file mode 100644 index 000000000..4519a4aa4 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go @@ -0,0 +1,72 @@ +// +build windows + +package ole + +import ( + "bytes" + "encoding/binary" + "reflect" + "syscall" + "unsafe" +) + +func (v *IInspectable) GetIids() (iids []*GUID, err error) { + var count uint32 + var array uintptr + hr, _, _ := syscall.Syscall( + v.VTable().GetIIds, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&count)), + uintptr(unsafe.Pointer(&array))) + if hr != 0 { + err = NewError(hr) + return + } + defer CoTaskMemFree(array) + + iids = make([]*GUID, count) + byteCount := count * uint32(unsafe.Sizeof(GUID{})) + slicehdr := reflect.SliceHeader{Data: array, Len: int(byteCount), Cap: int(byteCount)} + byteSlice := *(*[]byte)(unsafe.Pointer(&slicehdr)) + reader := bytes.NewReader(byteSlice) + for i := range iids { + guid := GUID{} + err = binary.Read(reader, binary.LittleEndian, &guid) + if err != nil { + return + } + iids[i] = &guid + } + return +} + +func (v *IInspectable) GetRuntimeClassName() (s string, err error) { + var hstring HString + hr, _, _ := syscall.Syscall( + v.VTable().GetRuntimeClassName, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&hstring)), + 0) + if hr != 0 { + err = NewError(hr) + return + } + s = hstring.String() + DeleteHString(hstring) + return +} + +func (v *IInspectable) GetTrustLevel() (level uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().GetTrustLevel, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&level)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go new file mode 100644 index 000000000..25f3a6f24 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go @@ -0,0 +1,21 @@ +package ole + +import "unsafe" + +type IProvideClassInfo struct { + IUnknown +} + +type IProvideClassInfoVtbl struct { + IUnknownVtbl + GetClassInfo uintptr +} + +func (v *IProvideClassInfo) VTable() *IProvideClassInfoVtbl { + return (*IProvideClassInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) { + cinfo, err = getClassInfo(v) + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go new file mode 100644 index 000000000..7e3cb63ea --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go new file mode 100644 index 000000000..2ad016394 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetClassInfo, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&tinfo)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo.go b/vendor/github.com/go-ole/go-ole/itypeinfo.go new file mode 100644 index 000000000..dd3c5e21b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo.go @@ -0,0 +1,34 @@ +package ole + +import "unsafe" + +type ITypeInfo struct { + IUnknown +} + +type ITypeInfoVtbl struct { + IUnknownVtbl + GetTypeAttr uintptr + GetTypeComp uintptr + GetFuncDesc uintptr + GetVarDesc uintptr + GetNames uintptr + GetRefTypeOfImplType uintptr + GetImplTypeFlags uintptr + GetIDsOfNames uintptr + Invoke uintptr + GetDocumentation uintptr + GetDllEntry uintptr + GetRefTypeInfo uintptr + AddressOfMember uintptr + CreateInstance uintptr + GetMops uintptr + GetContainingTypeLib uintptr + ReleaseTypeAttr uintptr + ReleaseFuncDesc uintptr + ReleaseVarDesc uintptr +} + +func (v *ITypeInfo) VTable() *ITypeInfoVtbl { + return (*ITypeInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go new file mode 100644 index 000000000..8364a659b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func (v *ITypeInfo) GetTypeAttr() (*TYPEATTR, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go new file mode 100644 index 000000000..54782b3da --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) { + hr, _, _ := syscall.Syscall( + uintptr(v.VTable().GetTypeAttr), + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&tattr)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown.go b/vendor/github.com/go-ole/go-ole/iunknown.go new file mode 100644 index 000000000..108f28ea6 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown.go @@ -0,0 +1,57 @@ +package ole + +import "unsafe" + +type IUnknown struct { + RawVTable *interface{} +} + +type IUnknownVtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr +} + +type UnknownLike interface { + QueryInterface(iid *GUID) (disp *IDispatch, err error) + AddRef() int32 + Release() int32 +} + +func (v *IUnknown) VTable() *IUnknownVtbl { + return (*IUnknownVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IUnknown) PutQueryInterface(interfaceID *GUID, obj interface{}) error { + return reflectQueryInterface(v, v.VTable().QueryInterface, interfaceID, obj) +} + +func (v *IUnknown) IDispatch(interfaceID *GUID) (dispatch *IDispatch, err error) { + err = v.PutQueryInterface(interfaceID, &dispatch) + return +} + +func (v *IUnknown) IEnumVARIANT(interfaceID *GUID) (enum *IEnumVARIANT, err error) { + err = v.PutQueryInterface(interfaceID, &enum) + return +} + +func (v *IUnknown) QueryInterface(iid *GUID) (*IDispatch, error) { + return queryInterface(v, iid) +} + +func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) { + unk, err := queryInterface(v, iid) + if err != nil { + panic(err) + } + return unk +} + +func (v *IUnknown) AddRef() int32 { + return addRef(v) +} + +func (v *IUnknown) Release() int32 { + return release(v) +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_func.go b/vendor/github.com/go-ole/go-ole/iunknown_func.go new file mode 100644 index 000000000..d0a62cfd7 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + return NewError(E_NOTIMPL) +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + return nil, NewError(E_NOTIMPL) +} + +func addRef(unk *IUnknown) int32 { + return 0 +} + +func release(unk *IUnknown) int32 { + return 0 +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_windows.go b/vendor/github.com/go-ole/go-ole/iunknown_windows.go new file mode 100644 index 000000000..ede5bb8c1 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unsafe" +) + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + selfValue := reflect.ValueOf(self).Elem() + objValue := reflect.ValueOf(obj).Elem() + + hr, _, _ := syscall.Syscall( + method, + 3, + selfValue.UnsafeAddr(), + uintptr(unsafe.Pointer(interfaceID)), + objValue.Addr().Pointer()) + if hr != 0 { + err = NewError(hr) + } + return +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + hr, _, _ := syscall.Syscall( + unk.VTable().QueryInterface, + 3, + uintptr(unsafe.Pointer(unk)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func addRef(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().AddRef, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} + +func release(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().Release, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} diff --git a/vendor/github.com/go-ole/go-ole/ole.go b/vendor/github.com/go-ole/go-ole/ole.go new file mode 100644 index 000000000..e2ae4f4bb --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ole.go @@ -0,0 +1,157 @@ +package ole + +import ( + "fmt" + "strings" +) + +// DISPPARAMS are the arguments that passed to methods or property. +type DISPPARAMS struct { + rgvarg uintptr + rgdispidNamedArgs uintptr + cArgs uint32 + cNamedArgs uint32 +} + +// EXCEPINFO defines exception info. +type EXCEPINFO struct { + wCode uint16 + wReserved uint16 + bstrSource *uint16 + bstrDescription *uint16 + bstrHelpFile *uint16 + dwHelpContext uint32 + pvReserved uintptr + pfnDeferredFillIn uintptr + scode uint32 +} + +// WCode return wCode in EXCEPINFO. +func (e EXCEPINFO) WCode() uint16 { + return e.wCode +} + +// SCODE return scode in EXCEPINFO. +func (e EXCEPINFO) SCODE() uint32 { + return e.scode +} + +// String convert EXCEPINFO to string. +func (e EXCEPINFO) String() string { + var src, desc, hlp string + if e.bstrSource == nil { + src = "" + } else { + src = BstrToString(e.bstrSource) + } + + if e.bstrDescription == nil { + desc = "" + } else { + desc = BstrToString(e.bstrDescription) + } + + if e.bstrHelpFile == nil { + hlp = "" + } else { + hlp = BstrToString(e.bstrHelpFile) + } + + return fmt.Sprintf( + "wCode: %#x, bstrSource: %v, bstrDescription: %v, bstrHelpFile: %v, dwHelpContext: %#x, scode: %#x", + e.wCode, src, desc, hlp, e.dwHelpContext, e.scode, + ) +} + +// Error implements error interface and returns error string. +func (e EXCEPINFO) Error() string { + if e.bstrDescription != nil { + return strings.TrimSpace(BstrToString(e.bstrDescription)) + } + + src := "Unknown" + if e.bstrSource != nil { + src = BstrToString(e.bstrSource) + } + + code := e.scode + if e.wCode != 0 { + code = uint32(e.wCode) + } + + return fmt.Sprintf("%v: %#x", src, code) +} + +// PARAMDATA defines parameter data type. +type PARAMDATA struct { + Name *int16 + Vt uint16 +} + +// METHODDATA defines method info. +type METHODDATA struct { + Name *uint16 + Data *PARAMDATA + Dispid int32 + Meth uint32 + CC int32 + CArgs uint32 + Flags uint16 + VtReturn uint32 +} + +// INTERFACEDATA defines interface info. +type INTERFACEDATA struct { + MethodData *METHODDATA + CMembers uint32 +} + +// Point is 2D vector type. +type Point struct { + X int32 + Y int32 +} + +// Msg is message between processes. +type Msg struct { + Hwnd uint32 + Message uint32 + Wparam int32 + Lparam int32 + Time uint32 + Pt Point +} + +// TYPEDESC defines data type. +type TYPEDESC struct { + Hreftype uint32 + VT uint16 +} + +// IDLDESC defines IDL info. +type IDLDESC struct { + DwReserved uint32 + WIDLFlags uint16 +} + +// TYPEATTR defines type info. +type TYPEATTR struct { + Guid GUID + Lcid uint32 + dwReserved uint32 + MemidConstructor int32 + MemidDestructor int32 + LpstrSchema *uint16 + CbSizeInstance uint32 + Typekind int32 + CFuncs uint16 + CVars uint16 + CImplTypes uint16 + CbSizeVft uint16 + CbAlignment uint16 + WTypeFlags uint16 + WMajorVerNum uint16 + WMinorVerNum uint16 + TdescAlias TYPEDESC + IdldescType IDLDESC +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection.go b/vendor/github.com/go-ole/go-ole/oleutil/connection.go new file mode 100644 index 000000000..60df73cda --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection.go @@ -0,0 +1,100 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +type stdDispatch struct { + lpVtbl *stdDispatchVtbl + ref int32 + iid *ole.GUID + iface interface{} + funcMap map[string]int32 +} + +type stdDispatchVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr + pGetTypeInfoCount uintptr + pGetTypeInfo uintptr + pGetIDsOfNames uintptr + pInvoke uintptr +} + +func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + *punk = nil + if ole.IsEqualGUID(iid, ole.IID_IUnknown) || + ole.IsEqualGUID(iid, ole.IID_IDispatch) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + if ole.IsEqualGUID(iid, pthis.iid) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + return ole.E_NOINTERFACE +} + +func dispAddRef(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref++ + return pthis.ref +} + +func dispRelease(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref-- + return pthis.ref +} + +func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + names := make([]string, len(wnames)) + for i := 0; i < len(names); i++ { + names[i] = ole.LpOleStrToString(wnames[i]) + } + for n := 0; n < namelen; n++ { + if id, ok := pthis.funcMap[names[n]]; ok { + pdisp[n] = id + } + } + return ole.S_OK +} + +func dispGetTypeInfoCount(pcount *int) uintptr { + if pcount != nil { + *pcount = 0 + } + return ole.S_OK +} + +func dispGetTypeInfo(ptypeif *uintptr) uintptr { + return ole.E_NOTIMPL +} + +func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + found := "" + for name, id := range pthis.funcMap { + if id == dispid { + found = name + } + } + if found != "" { + rv := reflect.ValueOf(pthis.iface).Elem() + rm := rv.MethodByName(found) + rr := rm.Call([]reflect.Value{}) + println(len(rr)) + return ole.S_OK + } + return ole.E_NOTIMPL +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go new file mode 100644 index 000000000..8818fb827 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go @@ -0,0 +1,10 @@ +// +build !windows + +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (uint32, error) { + return 0, ole.NewError(ole.E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go new file mode 100644 index 000000000..ab9c0d8dc --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "syscall" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) { + unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer) + if err != nil { + return + } + + container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown)) + var point *ole.IConnectionPoint + err = container.FindConnectionPoint(iid, &point) + if err != nil { + return + } + if edisp, ok := idisp.(*ole.IUnknown); ok { + cookie, err = point.Advise(edisp) + container.Release() + if err != nil { + return + } + } + rv := reflect.ValueOf(disp).Elem() + if rv.Type().Kind() == reflect.Struct { + dest := &stdDispatch{} + dest.lpVtbl = &stdDispatchVtbl{} + dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface) + dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef) + dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease) + dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount) + dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo) + dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames) + dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke) + dest.iface = disp + dest.iid = iid + cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest))) + container.Release() + if err != nil { + point.Release() + return + } + return + } + + container.Release() + + return 0, ole.NewError(ole.E_INVALIDARG) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go new file mode 100644 index 000000000..58347628f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go @@ -0,0 +1,6 @@ +// This file is here so go get succeeds as without it errors with: +// no buildable Go source files in ... +// +// +build !windows + +package oleutil diff --git a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go new file mode 100644 index 000000000..f7803c1e3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go @@ -0,0 +1,127 @@ +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +func ClassIDFrom(programID string) (classID *ole.GUID, err error) { + return ole.ClassIDFrom(programID) +} + +// CreateObject creates object from programID based on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func CreateObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.CreateInstance(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// GetActiveObject retrieves active object for program ID and interface ID based +// on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func GetActiveObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.GetActiveObject(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// CallMethod calls method on IDispatch with parameters. +func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_METHOD, params) +} + +// MustCallMethod calls method on IDispatch with parameters or panics. +func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := CallMethod(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// GetProperty retrieves property from IDispatch. +func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYGET, params) +} + +// MustGetProperty retrieves property from IDispatch or panics. +func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := GetProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutProperty mutates property. +func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUT, params) +} + +// MustPutProperty mutates property or panics. +func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutPropertyRef mutates property reference. +func PutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUTREF, params) +} + +// MustPutPropertyRef mutates property reference or panics. +func MustPutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutPropertyRef(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +func ForEach(disp *ole.IDispatch, f func(v *ole.VARIANT) error) error { + newEnum, err := disp.GetProperty("_NewEnum") + if err != nil { + return err + } + defer newEnum.Clear() + + enum, err := newEnum.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + defer enum.Release() + + for item, length, err := enum.Next(1); length > 0; item, length, err = enum.Next(1) { + if err != nil { + return err + } + if ferr := f(&item); ferr != nil { + return ferr + } + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/safearray.go b/vendor/github.com/go-ole/go-ole/safearray.go new file mode 100644 index 000000000..a5201b56c --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray.go @@ -0,0 +1,27 @@ +// Package is meant to retrieve and process safe array data returned from COM. + +package ole + +// SafeArrayBound defines the SafeArray boundaries. +type SafeArrayBound struct { + Elements uint32 + LowerBound int32 +} + +// SafeArray is how COM handles arrays. +type SafeArray struct { + Dimensions uint16 + FeaturesFlag uint16 + ElementsSize uint32 + LocksAmount uint32 + Data uint32 + Bounds [16]byte +} + +// SAFEARRAY is obsolete, exists for backwards compatibility. +// Use SafeArray +type SAFEARRAY SafeArray + +// SAFEARRAYBOUND is obsolete, exists for backwards compatibility. +// Use SafeArrayBound +type SAFEARRAYBOUND SafeArrayBound diff --git a/vendor/github.com/go-ole/go-ole/safearray_func.go b/vendor/github.com/go-ole/go-ole/safearray_func.go new file mode 100644 index 000000000..8ff0baa41 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_func.go @@ -0,0 +1,211 @@ +// +build !windows + +package ole + +import ( + "unsafe" +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +func safeArrayAccessData(safearray *SafeArray) (uintptr, error) { + return uintptr(0), NewError(E_NOTIMPL) +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int64) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int64, error) { + return int64(0), NewError(E_NOTIMPL) +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int64, error) { + return int64(0), NewError(E_NOTIMPL) +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (uint16, error) { + return uint16(0), NewError(E_NOTIMPL) +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (interface{}, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/safearray_windows.go b/vendor/github.com/go-ole/go-ole/safearray_windows.go new file mode 100644 index 000000000..b27936e24 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_windows.go @@ -0,0 +1,337 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +var ( + procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData") + procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData") + procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor") + procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx") + procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy") + procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData") + procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate") + procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx") + procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector") + procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx") + procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy") + procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData") + procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor") + procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim") + procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement") + procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize") + procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID") + procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound") + procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound") + procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype") + procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock") + procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex") + procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData") + procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock") + procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement") + //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO + //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO + procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo") + procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo") +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +// Todo: Test +func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) { + err = convertHresultToError( + procSafeArrayAccessData.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&element)))) + return +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptorEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayCopy.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) { + err = convertHresultToError( + procSafeArrayCopyData.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(duplicate)))) + return +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreate.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds))) + safearray = (*SafeArray)(unsafe.Pointer(&sa)) + return +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds)), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVector.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length)) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVectorEx.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) { + l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray))) + dimensions = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) { + l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray))) + length = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error { + return convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(pv))) +} + +// safeArrayGetElementString retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int64) (str string, err error) { + var element *int16 + err = convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(&element)))) + str = BstrToString(*(**uint16)(unsafe.Pointer(&element))) + SysFreeString(element) + return +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) { + err = convertHresultToError( + procSafeArrayGetIID.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&guid)))) + return +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int64, err error) { + err = convertHresultToError( + procSafeArrayGetLBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&lowerBound)))) + return +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int64, err error) { + err = convertHresultToError( + procSafeArrayGetUBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&upperBound)))) + return +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) { + err = convertHresultToError( + procSafeArrayGetVartype.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&varType)))) + return +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) (err error) { + err = convertHresultToError( + procSafeArrayPutElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(element)))) + return +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) { + err = convertHresultToError( + procSafeArrayGetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) { + err = convertHresultToError( + procSafeArraySetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayconversion.go b/vendor/github.com/go-ole/go-ole/safearrayconversion.go new file mode 100644 index 000000000..ffeb2b97b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayconversion.go @@ -0,0 +1,140 @@ +// Helper for converting SafeArray to array of objects. + +package ole + +import ( + "unsafe" +) + +type SafeArrayConversion struct { + Array *SafeArray +} + +func (sac *SafeArrayConversion) ToStringArray() (strings []string) { + totalElements, _ := sac.TotalElements(0) + strings = make([]string, totalElements) + + for i := int64(0); i < totalElements; i++ { + strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i) + } + + return +} + +func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) { + totalElements, _ := sac.TotalElements(0) + bytes = make([]byte, totalElements) + + for i := int64(0); i < totalElements; i++ { + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)])) + } + + return +} + +func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) { + totalElements, _ := sac.TotalElements(0) + values = make([]interface{}, totalElements) + vt, _ := safeArrayGetVartype(sac.Array) + + for i := 0; i < int(totalElements); i++ { + switch VT(vt) { + case VT_BOOL: + var v bool + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I1: + var v int8 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I2: + var v int16 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I4: + var v int32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I8: + var v int64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI1: + var v uint8 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI2: + var v uint16 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI4: + var v uint32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI8: + var v uint64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_R4: + var v float32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_R8: + var v float64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_BSTR: + var v string + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_VARIANT: + var v VARIANT + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v.Value() + default: + // TODO + } + } + + return +} + +func (sac *SafeArrayConversion) GetType() (varType uint16, err error) { + return safeArrayGetVartype(sac.Array) +} + +func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) { + return safeArrayGetDim(sac.Array) +} + +func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) { + return safeArrayGetElementSize(sac.Array) +} + +func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int64, err error) { + if index < 1 { + index = 1 + } + + // Get array bounds + var LowerBounds int64 + var UpperBounds int64 + + LowerBounds, err = safeArrayGetLBound(sac.Array, index) + if err != nil { + return + } + + UpperBounds, err = safeArrayGetUBound(sac.Array, index) + if err != nil { + return + } + + totalElements = UpperBounds - LowerBounds + 1 + return +} + +// Release Safe Array memory +func (sac *SafeArrayConversion) Release() { + safeArrayDestroy(sac.Array) +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayslices.go b/vendor/github.com/go-ole/go-ole/safearrayslices.go new file mode 100644 index 000000000..a9fa885f1 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayslices.go @@ -0,0 +1,33 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +func safeArrayFromByteSlice(slice []byte) *SafeArray { + array, _ := safeArrayCreateVector(VT_UI1, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []byte to SAFEARRAY") + } + + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(&v))) + } + return array +} + +func safeArrayFromStringSlice(slice []string) *SafeArray { + array, _ := safeArrayCreateVector(VT_BSTR, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []string to SAFEARRAY") + } + // SysAllocStringLen(s) + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(SysAllocStringLen(v)))) + } + return array +} diff --git a/vendor/github.com/go-ole/go-ole/utility.go b/vendor/github.com/go-ole/go-ole/utility.go new file mode 100644 index 000000000..99ee82dc3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/utility.go @@ -0,0 +1,101 @@ +package ole + +import ( + "unicode/utf16" + "unsafe" +) + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +// +// Helper that provides check against both Class ID from Program ID and Class ID from string. It is +// faster, if you know which you are using, to use the individual functions, but this will check +// against available functions for you. +func ClassIDFrom(programID string) (classID *GUID, err error) { + classID, err = CLSIDFromProgID(programID) + if err != nil { + classID, err = CLSIDFromString(programID) + if err != nil { + return + } + } + return +} + +// BytePtrToString converts byte pointer to a Go string. +func BytePtrToString(p *byte) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +// UTF16PtrToString is alias for LpOleStrToString. +// +// Kept for compatibility reasons. +func UTF16PtrToString(p *uint16) string { + return LpOleStrToString(p) +} + +// LpOleStrToString converts COM Unicode to Go string. +func LpOleStrToString(p *uint16) string { + if p == nil { + return "" + } + + length := lpOleStrLen(p) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + + return string(utf16.Decode(a)) +} + +// BstrToString converts COM binary string to Go string. +func BstrToString(p *uint16) string { + if p == nil { + return "" + } + length := SysStringLen((*int16)(unsafe.Pointer(p))) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return string(utf16.Decode(a)) +} + +// lpOleStrLen returns the length of Unicode string. +func lpOleStrLen(p *uint16) (length int64) { + if p == nil { + return 0 + } + + ptr := unsafe.Pointer(p) + + for i := 0; ; i++ { + if 0 == *(*uint16)(ptr) { + length = int64(i) + break + } + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return +} + +// convertHresultToError converts syscall to error, if call is unsuccessful. +func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) { + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/variables.go b/vendor/github.com/go-ole/go-ole/variables.go new file mode 100644 index 000000000..ebe00f1cf --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variables.go @@ -0,0 +1,16 @@ +// +build windows + +package ole + +import ( + "syscall" +) + +var ( + modcombase = syscall.NewLazyDLL("combase.dll") + modkernel32, _ = syscall.LoadDLL("kernel32.dll") + modole32, _ = syscall.LoadDLL("ole32.dll") + modoleaut32, _ = syscall.LoadDLL("oleaut32.dll") + modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll") + moduser32, _ = syscall.LoadDLL("user32.dll") +) diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go new file mode 100644 index 000000000..36969725e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant.go @@ -0,0 +1,105 @@ +package ole + +import "unsafe" + +// NewVariant returns new variant based on type and value. +func NewVariant(vt VT, val int64) VARIANT { + return VARIANT{VT: vt, Val: val} +} + +// ToIUnknown converts Variant to Unknown object. +func (v *VARIANT) ToIUnknown() *IUnknown { + if v.VT != VT_UNKNOWN { + return nil + } + return (*IUnknown)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToIDispatch converts variant to dispatch object. +func (v *VARIANT) ToIDispatch() *IDispatch { + if v.VT != VT_DISPATCH { + return nil + } + return (*IDispatch)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToArray converts variant to SafeArray helper. +func (v *VARIANT) ToArray() *SafeArrayConversion { + if v.VT != VT_SAFEARRAY { + if v.VT&VT_ARRAY == 0 { + return nil + } + } + var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val))) + return &SafeArrayConversion{safeArray} +} + +// ToString converts variant to Go string. +func (v *VARIANT) ToString() string { + if v.VT != VT_BSTR { + return "" + } + return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val))) +} + +// Clear the memory of variant object. +func (v *VARIANT) Clear() error { + return VariantClear(v) +} + +// Value returns variant value based on its type. +// +// Currently supported types: 2- and 4-byte integers, strings, bools. +// Note that 64-bit integers, datetimes, and other types are stored as strings +// and will be returned as strings. +// +// Needs to be further converted, because this returns an interface{}. +func (v *VARIANT) Value() interface{} { + switch v.VT { + case VT_I1: + return int8(v.Val) + case VT_UI1: + return uint8(v.Val) + case VT_I2: + return int16(v.Val) + case VT_UI2: + return uint16(v.Val) + case VT_I4: + return int32(v.Val) + case VT_UI4: + return uint32(v.Val) + case VT_I8: + return int64(v.Val) + case VT_UI8: + return uint64(v.Val) + case VT_INT: + return int(v.Val) + case VT_UINT: + return uint(v.Val) + case VT_INT_PTR: + return uintptr(v.Val) // TODO + case VT_UINT_PTR: + return uintptr(v.Val) + case VT_R4: + return *(*float32)(unsafe.Pointer(&v.Val)) + case VT_R8: + return *(*float64)(unsafe.Pointer(&v.Val)) + case VT_BSTR: + return v.ToString() + case VT_DATE: + // VT_DATE type will either return float64 or time.Time. + d := float64(v.Val) + date, err := GetVariantDate(d) + if err != nil { + return d + } + return date + case VT_UNKNOWN: + return v.ToIUnknown() + case VT_DISPATCH: + return v.ToIDispatch() + case VT_BOOL: + return v.Val != 0 + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/variant_386.go b/vendor/github.com/go-ole/go-ole/variant_386.go new file mode 100644 index 000000000..e73736bf3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_386.go @@ -0,0 +1,11 @@ +// +build 386 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_amd64.go b/vendor/github.com/go-ole/go-ole/variant_amd64.go new file mode 100644 index 000000000..dccdde132 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_amd64.go @@ -0,0 +1,12 @@ +// +build amd64 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_s390x.go b/vendor/github.com/go-ole/go-ole/variant_s390x.go new file mode 100644 index 000000000..9874ca66b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_s390x.go @@ -0,0 +1,12 @@ +// +build s390x + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/vt_string.go b/vendor/github.com/go-ole/go-ole/vt_string.go new file mode 100644 index 000000000..729b4a04d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/vt_string.go @@ -0,0 +1,58 @@ +// generated by stringer -output vt_string.go -type VT; DO NOT EDIT + +package ole + +import "fmt" + +const ( + _VT_name_0 = "VT_EMPTYVT_NULLVT_I2VT_I4VT_R4VT_R8VT_CYVT_DATEVT_BSTRVT_DISPATCHVT_ERRORVT_BOOLVT_VARIANTVT_UNKNOWNVT_DECIMAL" + _VT_name_1 = "VT_I1VT_UI1VT_UI2VT_UI4VT_I8VT_UI8VT_INTVT_UINTVT_VOIDVT_HRESULTVT_PTRVT_SAFEARRAYVT_CARRAYVT_USERDEFINEDVT_LPSTRVT_LPWSTR" + _VT_name_2 = "VT_RECORDVT_INT_PTRVT_UINT_PTR" + _VT_name_3 = "VT_FILETIMEVT_BLOBVT_STREAMVT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTVT_CFVT_CLSID" + _VT_name_4 = "VT_BSTR_BLOBVT_VECTOR" + _VT_name_5 = "VT_ARRAY" + _VT_name_6 = "VT_BYREF" + _VT_name_7 = "VT_RESERVED" + _VT_name_8 = "VT_ILLEGAL" +) + +var ( + _VT_index_0 = [...]uint8{0, 8, 15, 20, 25, 30, 35, 40, 47, 54, 65, 73, 80, 90, 100, 110} + _VT_index_1 = [...]uint8{0, 5, 11, 17, 23, 28, 34, 40, 47, 54, 64, 70, 82, 91, 105, 113, 122} + _VT_index_2 = [...]uint8{0, 9, 19, 30} + _VT_index_3 = [...]uint8{0, 11, 18, 27, 37, 55, 71, 85, 90, 98} + _VT_index_4 = [...]uint8{0, 12, 21} + _VT_index_5 = [...]uint8{0, 8} + _VT_index_6 = [...]uint8{0, 8} + _VT_index_7 = [...]uint8{0, 11} + _VT_index_8 = [...]uint8{0, 10} +) + +func (i VT) String() string { + switch { + case 0 <= i && i <= 14: + return _VT_name_0[_VT_index_0[i]:_VT_index_0[i+1]] + case 16 <= i && i <= 31: + i -= 16 + return _VT_name_1[_VT_index_1[i]:_VT_index_1[i+1]] + case 36 <= i && i <= 38: + i -= 36 + return _VT_name_2[_VT_index_2[i]:_VT_index_2[i+1]] + case 64 <= i && i <= 72: + i -= 64 + return _VT_name_3[_VT_index_3[i]:_VT_index_3[i+1]] + case 4095 <= i && i <= 4096: + i -= 4095 + return _VT_name_4[_VT_index_4[i]:_VT_index_4[i+1]] + case i == 8192: + return _VT_name_5 + case i == 16384: + return _VT_name_6 + case i == 32768: + return _VT_name_7 + case i == 65535: + return _VT_name_8 + default: + return fmt.Sprintf("VT(%d)", i) + } +} diff --git a/vendor/github.com/go-ole/go-ole/winrt.go b/vendor/github.com/go-ole/go-ole/winrt.go new file mode 100644 index 000000000..4e9eca732 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt.go @@ -0,0 +1,99 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unicode/utf8" + "unsafe" +) + +var ( + procRoInitialize = modcombase.NewProc("RoInitialize") + procRoActivateInstance = modcombase.NewProc("RoActivateInstance") + procRoGetActivationFactory = modcombase.NewProc("RoGetActivationFactory") + procWindowsCreateString = modcombase.NewProc("WindowsCreateString") + procWindowsDeleteString = modcombase.NewProc("WindowsDeleteString") + procWindowsGetStringRawBuffer = modcombase.NewProc("WindowsGetStringRawBuffer") +) + +func RoInitialize(thread_type uint32) (err error) { + hr, _, _ := procRoInitialize.Call(uintptr(thread_type)) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoActivateInstance.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoGetActivationFactory.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + u16 := syscall.StringToUTF16Ptr(s) + len := uint32(utf8.RuneCountInString(s)) + hr, _, _ := procWindowsCreateString.Call( + uintptr(unsafe.Pointer(u16)), + uintptr(len), + uintptr(unsafe.Pointer(&hstring))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + hr, _, _ := procWindowsDeleteString.Call(uintptr(hstring)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// String returns Go string value of HString. +func (h HString) String() string { + var u16buf uintptr + var u16len uint32 + u16buf, _, _ = procWindowsGetStringRawBuffer.Call( + uintptr(h), + uintptr(unsafe.Pointer(&u16len))) + + u16hdr := reflect.SliceHeader{Data: u16buf, Len: int(u16len), Cap: int(u16len)} + u16 := *(*[]uint16)(unsafe.Pointer(&u16hdr)) + return syscall.UTF16ToString(u16) +} diff --git a/vendor/github.com/go-ole/go-ole/winrt_doc.go b/vendor/github.com/go-ole/go-ole/winrt_doc.go new file mode 100644 index 000000000..52e6d74c9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt_doc.go @@ -0,0 +1,36 @@ +// +build !windows + +package ole + +// RoInitialize +func RoInitialize(thread_type uint32) (err error) { + return NewError(E_NOTIMPL) +} + +// RoActivateInstance +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// RoGetActivationFactory +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + return HString(uintptr(0)), NewError(E_NOTIMPL) +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + return NewError(E_NOTIMPL) +} + +// String returns Go string value of HString. +func (h HString) String() string { + return "" +} diff --git a/vendor/github.com/gogo/protobuf/io/uint32.go b/vendor/github.com/gogo/protobuf/io/uint32.go index fc43857dd..233b90924 100644 --- a/vendor/github.com/gogo/protobuf/io/uint32.go +++ b/vendor/github.com/gogo/protobuf/io/uint32.go @@ -120,7 +120,7 @@ func (this *uint32Reader) ReadMsg(msg proto.Message) error { if length < 0 || length > this.maxSize { return io.ErrShortBuffer } - if length >= len(this.buf) { + if length > len(this.buf) { this.buf = make([]byte, length) } _, err := io.ReadFull(this.r, this.buf[:length]) diff --git a/vendor/github.com/gogo/protobuf/proto/extensions.go b/vendor/github.com/gogo/protobuf/proto/extensions.go index 686bd2a09..341c6f57f 100644 --- a/vendor/github.com/gogo/protobuf/proto/extensions.go +++ b/vendor/github.com/gogo/protobuf/proto/extensions.go @@ -527,6 +527,7 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { // SetExtension sets the specified extension of pb to the specified value. func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { if epb, ok := pb.(extensionsBytes); ok { + ClearExtension(pb, extension) newb, err := encodeExtension(extension, value) if err != nil { return err diff --git a/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go b/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go index 53ebd8cca..6f1ae120e 100644 --- a/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go +++ b/vendor/github.com/gogo/protobuf/proto/extensions_gogo.go @@ -154,6 +154,10 @@ func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) return EncodeExtensionMap(m.extensionsWrite(), data) } +func EncodeInternalExtensionBackwards(m extendableProto, data []byte) (n int, err error) { + return EncodeExtensionMapBackwards(m.extensionsWrite(), data) +} + func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) { o := 0 for _, e := range m { @@ -169,6 +173,23 @@ func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) { return o, nil } +func EncodeExtensionMapBackwards(m map[int32]Extension, data []byte) (n int, err error) { + o := 0 + end := len(data) + for _, e := range m { + if err := e.Encode(); err != nil { + return 0, err + } + n := copy(data[end-len(e.enc):], e.enc) + if n != len(e.enc) { + return 0, io.ErrShortBuffer + } + end -= n + o += n + } + return o, nil +} + func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) { e := m[id] if err := e.Encode(); err != nil { diff --git a/vendor/github.com/gogo/protobuf/proto/lib.go b/vendor/github.com/gogo/protobuf/proto/lib.go index d17f80209..80db1c155 100644 --- a/vendor/github.com/gogo/protobuf/proto/lib.go +++ b/vendor/github.com/gogo/protobuf/proto/lib.go @@ -948,13 +948,19 @@ func isProto3Zero(v reflect.Value) bool { return false } -// ProtoPackageIsVersion2 is referenced from generated protocol buffer files -// to assert that that code is compatible with this version of the proto package. -const GoGoProtoPackageIsVersion2 = true +const ( + // ProtoPackageIsVersion3 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + GoGoProtoPackageIsVersion3 = true -// ProtoPackageIsVersion1 is referenced from generated protocol buffer files -// to assert that that code is compatible with this version of the proto package. -const GoGoProtoPackageIsVersion1 = true + // ProtoPackageIsVersion2 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + GoGoProtoPackageIsVersion2 = true + + // ProtoPackageIsVersion1 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + GoGoProtoPackageIsVersion1 = true +) // InternalMessageInfo is a type used internally by generated .pb.go files. // This type is not intended to be used by non-generated code. diff --git a/vendor/github.com/gogo/protobuf/proto/properties.go b/vendor/github.com/gogo/protobuf/proto/properties.go index c9e5fa020..62c55624a 100644 --- a/vendor/github.com/gogo/protobuf/proto/properties.go +++ b/vendor/github.com/gogo/protobuf/proto/properties.go @@ -400,6 +400,15 @@ func GetProperties(t reflect.Type) *StructProperties { return sprop } +type ( + oneofFuncsIface interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + oneofWrappersIface interface { + XXX_OneofWrappers() []interface{} + } +) + // getPropertiesLocked requires that propertiesMu is held. func getPropertiesLocked(t reflect.Type) *StructProperties { if prop, ok := propertiesMap[t]; ok { @@ -441,37 +450,40 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { // Re-order prop.order. sort.Sort(prop) - type oneofMessage interface { - XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) - } - if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok { + if isOneofMessage { var oots []interface{} - _, _, _, oots = om.XXX_OneofFuncs() - - // Interpret oneof metadata. - prop.OneofTypes = make(map[string]*OneofProperties) - for _, oot := range oots { - oop := &OneofProperties{ - Type: reflect.ValueOf(oot).Type(), // *T - Prop: new(Properties), - } - sft := oop.Type.Elem().Field(0) - oop.Prop.Name = sft.Name - oop.Prop.Parse(sft.Tag.Get("protobuf")) - // There will be exactly one interface field that - // this new value is assignable to. - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if f.Type.Kind() != reflect.Interface { - continue + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oots = m.XXX_OneofFuncs() + case oneofWrappersIface: + oots = m.XXX_OneofWrappers() + } + if len(oots) > 0 { + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), } - if !oop.Type.AssignableTo(f.Type) { - continue + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break } - oop.Field = i - break + prop.OneofTypes[oop.Prop.OrigName] = oop } - prop.OneofTypes[oop.Prop.OrigName] = oop } } diff --git a/vendor/github.com/gogo/protobuf/proto/table_marshal.go b/vendor/github.com/gogo/protobuf/proto/table_marshal.go index 9b1538d05..db9927a0c 100644 --- a/vendor/github.com/gogo/protobuf/proto/table_marshal.go +++ b/vendor/github.com/gogo/protobuf/proto/table_marshal.go @@ -389,8 +389,13 @@ func (u *marshalInfo) computeMarshalInfo() { // get oneof implementers var oneofImplementers []interface{} // gogo: isOneofMessage is needed for embedded oneof messages, without a marshaler and unmarshaler - if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok && isOneofMessage { - _, _, _, oneofImplementers = m.XXX_OneofFuncs() + if isOneofMessage { + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + case oneofWrappersIface: + oneofImplementers = m.XXX_OneofWrappers() + } } // normal fields @@ -519,10 +524,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI } } -type oneofMessage interface { - XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) -} - // wiretype returns the wire encoding of the type. func wiretype(encoding string) uint64 { switch encoding { diff --git a/vendor/github.com/gogo/protobuf/proto/table_merge.go b/vendor/github.com/gogo/protobuf/proto/table_merge.go index f520106e0..60dcf70d1 100644 --- a/vendor/github.com/gogo/protobuf/proto/table_merge.go +++ b/vendor/github.com/gogo/protobuf/proto/table_merge.go @@ -530,6 +530,25 @@ func (mi *mergeInfo) computeMergeInfo() { } case reflect.Struct: switch { + case isSlice && !isPointer: // E.g. []pb.T + mergeInfo := getMergeInfo(tf) + zero := reflect.Zero(tf) + mfi.merge = func(dst, src pointer) { + // TODO: Make this faster? + dstsp := dst.asPointerTo(f.Type) + dsts := dstsp.Elem() + srcs := src.asPointerTo(f.Type).Elem() + for i := 0; i < srcs.Len(); i++ { + dsts = reflect.Append(dsts, zero) + srcElement := srcs.Index(i).Addr() + dstElement := dsts.Index(dsts.Len() - 1).Addr() + mergeInfo.merge(valToPointer(dstElement), valToPointer(srcElement)) + } + if dsts.IsNil() { + dsts = reflect.MakeSlice(f.Type, 0, 0) + } + dstsp.Elem().Set(dsts) + } case !isPointer: mergeInfo := getMergeInfo(tf) mfi.merge = func(dst, src pointer) { diff --git a/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go b/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go index bb2622f28..937229386 100644 --- a/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go +++ b/vendor/github.com/gogo/protobuf/proto/table_unmarshal.go @@ -371,15 +371,18 @@ func (u *unmarshalInfo) computeUnmarshalInfo() { } // Find any types associated with oneof fields. - // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? - fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") // gogo: len(oneofFields) > 0 is needed for embedded oneof messages, without a marshaler and unmarshaler - if fn.IsValid() && len(oneofFields) > 0 { - res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} - for i := res.Len() - 1; i >= 0; i-- { - v := res.Index(i) // interface{} - tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X - typ := tptr.Elem() // Msg_X + if len(oneofFields) > 0 { + var oneofImplementers []interface{} + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + case oneofWrappersIface: + oneofImplementers = m.XXX_OneofWrappers() + } + for _, v := range oneofImplementers { + tptr := reflect.TypeOf(v) // *Msg_X + typ := tptr.Elem() // Msg_X f := typ.Field(0) // oneof implementers have one field baseUnmarshal := fieldUnmarshaler(&f) @@ -407,11 +410,12 @@ func (u *unmarshalInfo) computeUnmarshalInfo() { u.setTag(fieldNum, of.field, unmarshal, 0, name) } } + } } // Get extension ranges, if any. - fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") if fn.IsValid() { if !u.extensions.IsValid() && !u.oldExtensions.IsValid() && !u.bytesExtensions.IsValid() { panic("a message with extensions, but no extensions field in " + t.Name()) diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go index 6fde25f50..0651c91e4 100644 --- a/vendor/github.com/golang/mock/gomock/controller.go +++ b/vendor/github.com/golang/mock/gomock/controller.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// GoMock - a mock framework for Go. +// Package gomock is a mock framework for Go. // // Standard usage: // (1) Define an interface that you wish to mock. @@ -63,8 +63,8 @@ import ( "sync" ) -// A TestReporter is something that can be used to report test failures. -// It is satisfied by the standard library's *testing.T. +// A TestReporter is something that can be used to report test failures. It +// is satisfied by the standard library's *testing.T. type TestReporter interface { Errorf(format string, args ...interface{}) Fatalf(format string, args ...interface{}) @@ -77,14 +77,35 @@ type TestHelper interface { Helper() } -// A Controller represents the top-level control of a mock ecosystem. -// It defines the scope and lifetime of mock objects, as well as their expectations. -// It is safe to call Controller's methods from multiple goroutines. +// A Controller represents the top-level control of a mock ecosystem. It +// defines the scope and lifetime of mock objects, as well as their +// expectations. It is safe to call Controller's methods from multiple +// goroutines. Each test should create a new Controller and invoke Finish via +// defer. +// +// func TestFoo(t *testing.T) { +// ctrl := gomock.NewController(st) +// defer ctrl.Finish() +// // .. +// } +// +// func TestBar(t *testing.T) { +// t.Run("Sub-Test-1", st) { +// ctrl := gomock.NewController(st) +// defer ctrl.Finish() +// // .. +// }) +// t.Run("Sub-Test-2", st) { +// ctrl := gomock.NewController(st) +// defer ctrl.Finish() +// // .. +// }) +// }) type Controller struct { // T should only be called within a generated mock. It is not intended to // be used in user code and may be changed in future versions. T is the // TestReporter passed in when creating the Controller via NewController. - // If the TestReporter does not implment a TestHelper it will be wrapped + // If the TestReporter does not implement a TestHelper it will be wrapped // with a nopTestHelper. T TestHelper mu sync.Mutex @@ -92,6 +113,8 @@ type Controller struct { finished bool } +// NewController returns a new Controller. It is the preferred way to create a +// Controller. func NewController(t TestReporter) *Controller { h, ok := t.(TestHelper) if !ok { @@ -135,6 +158,7 @@ type nopTestHelper struct { func (h nopTestHelper) Helper() {} +// RecordCall is called by a mock. It should not be called by user code. func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call { ctrl.T.Helper() @@ -148,6 +172,7 @@ func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ... panic("unreachable") } +// RecordCallWithMethodType is called by a mock. It should not be called by user code. func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call { ctrl.T.Helper() @@ -160,6 +185,7 @@ func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method st return call } +// Call is called by a mock. It should not be called by user code. func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} { ctrl.T.Helper() @@ -200,6 +226,9 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf return rets } +// Finish checks to see if all the methods that were expected to be called +// were called. It should be invoked for each Controller. It is not idempotent +// and therefore can only be invoked once. func (ctrl *Controller) Finish() { ctrl.T.Helper() diff --git a/vendor/github.com/golang/mock/gomock/matchers.go b/vendor/github.com/golang/mock/gomock/matchers.go index 189796f86..fbff06062 100644 --- a/vendor/github.com/golang/mock/gomock/matchers.go +++ b/vendor/github.com/golang/mock/gomock/matchers.go @@ -98,9 +98,30 @@ func (m assignableToTypeOfMatcher) String() string { } // Constructors -func Any() Matcher { return anyMatcher{} } +// Any returns a matcher that always matches. +func Any() Matcher { return anyMatcher{} } + +// Eq returns a matcher that matches on equality. +// +// Example usage: +// Eq(5).Matches(5) // returns true +// Eq(5).Matches(4) // returns false func Eq(x interface{}) Matcher { return eqMatcher{x} } -func Nil() Matcher { return nilMatcher{} } + +// Nil returns a matcher that matches if the received value is nil. +// +// Example usage: +// var x *bytes.Buffer +// Nil().Matches(x) // returns true +// x = &bytes.Buffer{} +// Nil().Matches(x) // returns false +func Nil() Matcher { return nilMatcher{} } + +// Not reverses the results of its given child matcher. +// +// Example usage: +// Not(Eq(5)).Matches(4) // returns true +// Not(Eq(5)).Matches(5) // returns false func Not(x interface{}) Matcher { if m, ok := x.(Matcher); ok { return notMatcher{m} @@ -112,11 +133,9 @@ func Not(x interface{}) Matcher { // function is assignable to the type of the parameter to this function. // // Example usage: -// -// dbMock.EXPECT(). -// Insert(gomock.AssignableToTypeOf(&EmployeeRecord{})). -// Return(errors.New("DB error")) -// +// var s fmt.Stringer = &bytes.Buffer{} +// AssignableToTypeOf(s).Matches(time.Second) // returns true +// AssignableToTypeOf(s).Matches(99) // returns false func AssignableToTypeOf(x interface{}) Matcher { return assignableToTypeOfMatcher{reflect.TypeOf(x)} } diff --git a/vendor/github.com/gorilla/websocket/.travis.yml b/vendor/github.com/gorilla/websocket/.travis.yml deleted file mode 100644 index a49db51c4..000000000 --- a/vendor/github.com/gorilla/websocket/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: 1.11.x - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md index 20e391f86..0827d059c 100644 --- a/vendor/github.com/gorilla/websocket/README.md +++ b/vendor/github.com/gorilla/websocket/README.md @@ -1,11 +1,11 @@ # Gorilla WebSocket +[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) +[![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket) + Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. -[![Build Status](https://travis-ci.org/gorilla/websocket.svg?branch=master)](https://travis-ci.org/gorilla/websocket) -[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) - ### Documentation * [API Reference](http://godoc.org/github.com/gorilla/websocket) @@ -27,7 +27,7 @@ package API is stable. ### Protocol Compliance The Gorilla WebSocket package passes the server tests in the [Autobahn Test -Suite](http://autobahn.ws/testsuite) using the application in the [examples/autobahn +Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). ### Gorilla WebSocket compared with other packages @@ -40,7 +40,7 @@ subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn RFC 6455 Features -Passes Autobahn Test SuiteYesNo +Passes Autobahn Test SuiteYesNo Receive fragmented messageYesNo, see note 1 Send close messageYesNo Send pings and receive pongsYesNo diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go index 2e32fd506..962c06a39 100644 --- a/vendor/github.com/gorilla/websocket/client.go +++ b/vendor/github.com/gorilla/websocket/client.go @@ -70,7 +70,7 @@ type Dialer struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration - // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer // size is zero, then a useful default size is used. The I/O buffer sizes // do not limit the size of the messages that can be sent or received. ReadBufferSize, WriteBufferSize int @@ -140,7 +140,7 @@ var nilDialer = *DefaultDialer // Use the response.Header to get the selected subprotocol // (Sec-WebSocket-Protocol) and cookies (Set-Cookie). // -// The context will be used in the request and in the Dialer +// The context will be used in the request and in the Dialer. // // If the WebSocket handshake fails, ErrBadHandshake is returned along with a // non-nil *http.Response so that callers can handle redirects, authentication, diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index d2a21c148..6f17cd299 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -260,10 +260,12 @@ type Conn struct { newCompressionWriter func(io.WriteCloser, int) io.WriteCloser // Read fields - reader io.ReadCloser // the current reader returned to the application - readErr error - br *bufio.Reader - readRemaining int64 // bytes remaining in current frame. + reader io.ReadCloser // the current reader returned to the application + readErr error + br *bufio.Reader + // bytes remaining in current frame. + // set setReadRemaining to safely update this value and prevent overflow + readRemaining int64 readFinal bool // true the current message has more frames. readLength int64 // Message size. readLimit int64 // Maximum message size. @@ -320,6 +322,17 @@ func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int, return c } +// setReadRemaining tracks the number of bytes remaining on the connection. If n +// overflows, an ErrReadLimit is returned. +func (c *Conn) setReadRemaining(n int64) error { + if n < 0 { + return ErrReadLimit + } + + c.readRemaining = n + return nil +} + // Subprotocol returns the negotiated protocol for the connection. func (c *Conn) Subprotocol() string { return c.subprotocol @@ -451,7 +464,8 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er return err } -func (c *Conn) prepWrite(messageType int) error { +// beginMessage prepares a connection and message writer for a new message. +func (c *Conn) beginMessage(mw *messageWriter, messageType int) error { // Close previous writer if not already closed by the application. It's // probably better to return an error in this situation, but we cannot // change this without breaking existing applications. @@ -471,6 +485,10 @@ func (c *Conn) prepWrite(messageType int) error { return err } + mw.c = c + mw.frameType = messageType + mw.pos = maxFrameHeaderSize + if c.writeBuf == nil { wpd, ok := c.writePool.Get().(writePoolData) if ok { @@ -491,16 +509,11 @@ func (c *Conn) prepWrite(messageType int) error { // All message types (TextMessage, BinaryMessage, CloseMessage, PingMessage and // PongMessage) are supported. func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { - if err := c.prepWrite(messageType); err != nil { + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { return nil, err } - - mw := &messageWriter{ - c: c, - frameType: messageType, - pos: maxFrameHeaderSize, - } - c.writer = mw + c.writer = &mw if c.newCompressionWriter != nil && c.enableWriteCompression && isData(messageType) { w := c.newCompressionWriter(c.writer, c.compressionLevel) mw.compress = true @@ -517,10 +530,16 @@ type messageWriter struct { err error } -func (w *messageWriter) fatal(err error) error { +func (w *messageWriter) endMessage(err error) error { if w.err != nil { - w.err = err - w.c.writer = nil + return err + } + c := w.c + w.err = err + c.writer = nil + if c.writePool != nil { + c.writePool.Put(writePoolData{buf: c.writeBuf}) + c.writeBuf = nil } return err } @@ -534,7 +553,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { // Check for invalid control frames. if isControl(w.frameType) && (!final || length > maxControlFramePayloadSize) { - return w.fatal(errInvalidControlFrame) + return w.endMessage(errInvalidControlFrame) } b0 := byte(w.frameType) @@ -579,7 +598,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { copy(c.writeBuf[maxFrameHeaderSize-4:], key[:]) maskBytes(key, 0, c.writeBuf[maxFrameHeaderSize:w.pos]) if len(extra) > 0 { - return c.writeFatal(errors.New("websocket: internal error, extra used in client mode")) + return w.endMessage(c.writeFatal(errors.New("websocket: internal error, extra used in client mode"))) } } @@ -600,15 +619,11 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error { c.isWriting = false if err != nil { - return w.fatal(err) + return w.endMessage(err) } if final { - c.writer = nil - if c.writePool != nil { - c.writePool.Put(writePoolData{buf: c.writeBuf}) - c.writeBuf = nil - } + w.endMessage(errWriteClosed) return nil } @@ -706,11 +721,7 @@ func (w *messageWriter) Close() error { if w.err != nil { return w.err } - if err := w.flushFrame(true, nil); err != nil { - return err - } - w.err = errWriteClosed - return nil + return w.flushFrame(true, nil) } // WritePreparedMessage writes prepared message into connection. @@ -742,10 +753,10 @@ func (c *Conn) WriteMessage(messageType int, data []byte) error { if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) { // Fast path with no allocations and single frame. - if err := c.prepWrite(messageType); err != nil { + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { return err } - mw := messageWriter{c: c, frameType: messageType, pos: maxFrameHeaderSize} n := copy(c.writeBuf[mw.pos:], data) mw.pos += n data = data[n:] @@ -792,7 +803,7 @@ func (c *Conn) advanceFrame() (int, error) { final := p[0]&finalBit != 0 frameType := int(p[0] & 0xf) mask := p[1]&maskBit != 0 - c.readRemaining = int64(p[1] & 0x7f) + c.setReadRemaining(int64(p[1] & 0x7f)) c.readDecompress = false if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 { @@ -826,7 +837,17 @@ func (c *Conn) advanceFrame() (int, error) { return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType)) } - // 3. Read and parse frame length. + // 3. Read and parse frame length as per + // https://tools.ietf.org/html/rfc6455#section-5.2 + // + // The length of the "Payload data", in bytes: if 0-125, that is the payload + // length. + // - If 126, the following 2 bytes interpreted as a 16-bit unsigned + // integer are the payload length. + // - If 127, the following 8 bytes interpreted as + // a 64-bit unsigned integer (the most significant bit MUST be 0) are the + // payload length. Multibyte length quantities are expressed in network byte + // order. switch c.readRemaining { case 126: @@ -834,13 +855,19 @@ func (c *Conn) advanceFrame() (int, error) { if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint16(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint16(p))); err != nil { + return noFrame, err + } case 127: p, err := c.read(8) if err != nil { return noFrame, err } - c.readRemaining = int64(binary.BigEndian.Uint64(p)) + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint64(p))); err != nil { + return noFrame, err + } } // 4. Handle frame masking. @@ -863,6 +890,12 @@ func (c *Conn) advanceFrame() (int, error) { if frameType == continuationFrame || frameType == TextMessage || frameType == BinaryMessage { c.readLength += c.readRemaining + // Don't allow readLength to overflow in the presence of a large readRemaining + // counter. + if c.readLength < 0 { + return noFrame, ErrReadLimit + } + if c.readLimit > 0 && c.readLength > c.readLimit { c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait)) return noFrame, ErrReadLimit @@ -876,7 +909,7 @@ func (c *Conn) advanceFrame() (int, error) { var payload []byte if c.readRemaining > 0 { payload, err = c.read(int(c.readRemaining)) - c.readRemaining = 0 + c.setReadRemaining(0) if err != nil { return noFrame, err } @@ -949,6 +982,7 @@ func (c *Conn) NextReader() (messageType int, r io.Reader, err error) { c.readErr = hideTempErr(err) break } + if frameType == TextMessage || frameType == BinaryMessage { c.messageReader = &messageReader{c} c.reader = c.messageReader @@ -989,7 +1023,9 @@ func (r *messageReader) Read(b []byte) (int, error) { if c.isServer { c.readMaskPos = maskBytes(c.readMaskKey, c.readMaskPos, b[:n]) } - c.readRemaining -= int64(n) + rem := c.readRemaining + rem -= int64(n) + c.setReadRemaining(rem) if c.readRemaining > 0 && c.readErr == io.EOF { c.readErr = errUnexpectedEOF } @@ -1041,7 +1077,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error { return c.conn.SetReadDeadline(t) } -// SetReadLimit sets the maximum size for a message read from the peer. If a +// SetReadLimit sets the maximum size in bytes for a message read from the peer. If a // message exceeds the limit, the connection sends a close message to the peer // and returns ErrReadLimit to the application. func (c *Conn) SetReadLimit(limit int64) { diff --git a/vendor/github.com/gorilla/websocket/doc.go b/vendor/github.com/gorilla/websocket/doc.go index dcce1a63c..c6f4df896 100644 --- a/vendor/github.com/gorilla/websocket/doc.go +++ b/vendor/github.com/gorilla/websocket/doc.go @@ -151,6 +151,53 @@ // checking. The application is responsible for checking the Origin header // before calling the Upgrade function. // +// Buffers +// +// Connections buffer network input and output to reduce the number +// of system calls when reading or writing messages. +// +// Write buffers are also used for constructing WebSocket frames. See RFC 6455, +// Section 5 for a discussion of message framing. A WebSocket frame header is +// written to the network each time a write buffer is flushed to the network. +// Decreasing the size of the write buffer can increase the amount of framing +// overhead on the connection. +// +// The buffer sizes in bytes are specified by the ReadBufferSize and +// WriteBufferSize fields in the Dialer and Upgrader. The Dialer uses a default +// size of 4096 when a buffer size field is set to zero. The Upgrader reuses +// buffers created by the HTTP server when a buffer size field is set to zero. +// The HTTP server buffers have a size of 4096 at the time of this writing. +// +// The buffer sizes do not limit the size of a message that can be read or +// written by a connection. +// +// Buffers are held for the lifetime of the connection by default. If the +// Dialer or Upgrader WriteBufferPool field is set, then a connection holds the +// write buffer only when writing a message. +// +// Applications should tune the buffer sizes to balance memory use and +// performance. Increasing the buffer size uses more memory, but can reduce the +// number of system calls to read or write the network. In the case of writing, +// increasing the buffer size can reduce the number of frame headers written to +// the network. +// +// Some guidelines for setting buffer parameters are: +// +// Limit the buffer sizes to the maximum expected message size. Buffers larger +// than the largest message do not provide any benefit. +// +// Depending on the distribution of message sizes, setting the buffer size to +// to a value less than the maximum expected message size can greatly reduce +// memory use with a small impact on performance. Here's an example: If 99% of +// the messages are smaller than 256 bytes and the maximum message size is 512 +// bytes, then a buffer size of 256 bytes will result in 1.01 more system calls +// than a buffer size of 512 bytes. The memory savings is 50%. +// +// A write buffer pool is useful when the application has a modest number +// writes over a large number of connections. when buffers are pooled, a larger +// buffer size has a reduced impact on total memory use and has the benefit of +// reducing system calls and frame overhead. +// // Compression EXPERIMENTAL // // Per message compression extensions (RFC 7692) are experimentally supported diff --git a/vendor/github.com/gorilla/websocket/go.mod b/vendor/github.com/gorilla/websocket/go.mod new file mode 100644 index 000000000..1a7afd502 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.mod @@ -0,0 +1,3 @@ +module github.com/gorilla/websocket + +go 1.12 diff --git a/vendor/github.com/gorilla/websocket/go.sum b/vendor/github.com/gorilla/websocket/go.sum new file mode 100644 index 000000000..cf4fbbaa0 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= diff --git a/vendor/github.com/gorilla/websocket/join.go b/vendor/github.com/gorilla/websocket/join.go new file mode 100644 index 000000000..c64f8c829 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/join.go @@ -0,0 +1,42 @@ +// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "io" + "strings" +) + +// JoinMessages concatenates received messages to create a single io.Reader. +// The string term is appended to each message. The returned reader does not +// support concurrent calls to the Read method. +func JoinMessages(c *Conn, term string) io.Reader { + return &joinReader{c: c, term: term} +} + +type joinReader struct { + c *Conn + term string + r io.Reader +} + +func (r *joinReader) Read(p []byte) (int, error) { + if r.r == nil { + var err error + _, r.r, err = r.c.NextReader() + if err != nil { + return 0, err + } + if r.term != "" { + r.r = io.MultiReader(r.r, strings.NewReader(r.term)) + } + } + n, err := r.r.Read(p) + if err == io.EOF { + err = nil + r.r = nil + } + return n, err +} diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go index bf2478e43..e87a8c9f0 100644 --- a/vendor/github.com/gorilla/websocket/proxy.go +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -22,18 +22,18 @@ func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { func init() { proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { - return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil + return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil }) } type httpProxyDialer struct { - proxyURL *url.URL - fowardDial func(network, addr string) (net.Conn, error) + proxyURL *url.URL + forwardDial func(network, addr string) (net.Conn, error) } func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { hostPort, _ := hostPortNoPort(hpd.proxyURL) - conn, err := hpd.fowardDial(network, hostPort) + conn, err := hpd.forwardDial(network, hostPort) if err != nil { return nil, err } diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go index a761824b3..887d55891 100644 --- a/vendor/github.com/gorilla/websocket/server.go +++ b/vendor/github.com/gorilla/websocket/server.go @@ -27,7 +27,7 @@ type Upgrader struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration - // ReadBufferSize and WriteBufferSize specify I/O buffer sizes. If a buffer + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer // size is zero, then buffers allocated by the HTTP server are used. The // I/O buffer sizes do not limit the size of the messages that can be sent // or received. @@ -153,7 +153,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade challengeKey := r.Header.Get("Sec-Websocket-Key") if challengeKey == "" { - return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: `Sec-WebSocket-Key' header is missing or blank") + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") } subprotocol := u.selectSubprotocol(r, responseHeader) diff --git a/vendor/github.com/gorilla/websocket/util.go b/vendor/github.com/gorilla/websocket/util.go index 354001e1e..7bf2f66c6 100644 --- a/vendor/github.com/gorilla/websocket/util.go +++ b/vendor/github.com/gorilla/websocket/util.go @@ -31,68 +31,113 @@ func generateChallengeKey() (string, error) { return base64.StdEncoding.EncodeToString(p), nil } -// Octet types from RFC 2616. -var octetTypes [256]byte - -const ( - isTokenOctet = 1 << iota - isSpaceOctet -) - -func init() { - // From RFC 2616 - // - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t byte - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 - if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { - t |= isSpaceOctet - } - if isChar && !isCtl && !isSeparator { - t |= isTokenOctet - } - octetTypes[c] = t - } +// Token octets per RFC 2616. +var isTokenOctet = [256]bool{ + '!': true, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '*': true, + '+': true, + '-': true, + '.': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'W': true, + 'V': true, + 'X': true, + 'Y': true, + 'Z': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '|': true, + '~': true, } +// skipSpace returns a slice of the string s with all leading RFC 2616 linear +// whitespace removed. func skipSpace(s string) (rest string) { i := 0 for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpaceOctet == 0 { + if b := s[i]; b != ' ' && b != '\t' { break } } return s[i:] } +// nextToken returns the leading RFC 2616 token of s and the string following +// the token. func nextToken(s string) (token, rest string) { i := 0 for ; i < len(s); i++ { - if octetTypes[s[i]]&isTokenOctet == 0 { + if !isTokenOctet[s[i]] { break } } return s[:i], s[i:] } +// nextTokenOrQuoted returns the leading token or quoted string per RFC 2616 +// and the string following the token or quoted string. func nextTokenOrQuoted(s string) (value string, rest string) { if !strings.HasPrefix(s, "\"") { return nextToken(s) @@ -128,7 +173,8 @@ func nextTokenOrQuoted(s string) (value string, rest string) { return "", "" } -// equalASCIIFold returns true if s is equal to t with ASCII case folding. +// equalASCIIFold returns true if s is equal to t with ASCII case folding as +// defined in RFC 4790. func equalASCIIFold(s, t string) bool { for s != "" && t != "" { sr, size := utf8.DecodeRuneInString(s) diff --git a/vendor/github.com/ipfs/go-cid/cid.go b/vendor/github.com/ipfs/go-cid/cid.go index 6b62d30d7..d88b66113 100644 --- a/vendor/github.com/ipfs/go-cid/cid.go +++ b/vendor/github.com/ipfs/go-cid/cid.go @@ -62,6 +62,7 @@ const ( DagProtobuf = 0x70 DagCBOR = 0x71 + Libp2pKey = 0x72 GitRaw = 0x78 @@ -90,6 +91,7 @@ var Codecs = map[string]uint64{ "raw": Raw, "protobuf": DagProtobuf, "cbor": DagCBOR, + "libp2p-key": Libp2pKey, "git-raw": GitRaw, "eth-block": EthBlock, "eth-block-list": EthBlockList, diff --git a/vendor/github.com/karalabe/hid/.travis.yml b/vendor/github.com/karalabe/hid/.travis.yml deleted file mode 100644 index 54c6bbdb4..000000000 --- a/vendor/github.com/karalabe/hid/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: go - -matrix: - include: - - os: linux - dist: trusty - go: 1.5.x - - os: linux - dist: trusty - go: 1.6.x - - os: linux - dist: trusty - go: 1.7.x - - os: linux - dist: trusty - go: 1.8.x - - os: linux - dist: trusty - go: 1.9.x - - os: linux - dist: precise - go: 1.9.x - - os: linux - dist: precise - go: 1.10.x - - os: osx - go: 1.10.x - -script: - - go install ./... - - go test -v ./... diff --git a/vendor/github.com/karalabe/hid/LICENSE.md b/vendor/github.com/karalabe/hid/LICENSE.md deleted file mode 100644 index 230d1daeb..000000000 --- a/vendor/github.com/karalabe/hid/LICENSE.md +++ /dev/null @@ -1,8 +0,0 @@ -The components of `hid` are licensed as such: - - * `hidapi` is released under the [3-clause BSD](https://github.com/signal11/hidapi/blob/master/LICENSE-bsd.txt) license. - * `libusb` is released under the [GNU LGPL 2.1](https://github.com/libusb/libusb/blob/master/COPYING)license. - * `go.hid` is released under the [2-clause BSD](https://github.com/GeertJohan/go.hid/blob/master/LICENSE) license. - * `gowchar` is released under the [3-clause BSD](https://github.com/orofarne/gowchar/blob/master/LICENSE) license. - -Given the above, `hid` is licensed under GNU LGPL 2.1 or later on Linux and 3-clause BSD on other platforms. diff --git a/vendor/github.com/karalabe/hid/README.md b/vendor/github.com/karalabe/hid/README.md deleted file mode 100644 index 2851ffe42..000000000 --- a/vendor/github.com/karalabe/hid/README.md +++ /dev/null @@ -1,53 +0,0 @@ -[![Travis][travisimg]][travisurl] -[![AppVeyor][appveyorimg]][appveyorurl] -[![GoDoc][docimg]][docurl] - -[travisimg]: https://travis-ci.org/karalabe/hid.svg?branch=master -[travisurl]: https://travis-ci.org/karalabe/hid -[appveyorimg]: https://ci.appveyor.com/api/projects/status/plroy54odykb0ch3/branch/master?svg=true -[appveyorurl]: https://ci.appveyor.com/project/karalabe/hid -[docimg]: https://godoc.org/github.com/karalabe/hid?status.svg -[docurl]: https://godoc.org/github.com/karalabe/hid - -# Gopher Interface Devices (USB HID) - -The `hid` package is a cross platform library for accessing and communicating with USB Human Interface -Devices (HID). It is an alternative package to [`gousb`](https://github.com/karalabe/gousb) for use -cases where devices support this ligher mode of operation (e.g. input devices, hardware crypto wallets). - -The package wraps [`hidapi`](https://github.com/signal11/hidapi) for accessing OS specific USB HID APIs -directly instead of using low level USB constructs, which might have permission issues on some platforms. -On Linux the package also wraps [`libusb`](https://github.com/libusb/libusb). Both of these dependencies -are vendored directly into the repository and wrapped using CGO, making the `hid` package self-contained -and go-gettable. - -Supported platforms at the moment are Linux, macOS and Windows (exclude constraints are also specified -for Android and iOS to allow smoother vendoring into cross platform projects). - -## Cross-compiling - -Using `go get` the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration `hid.Enumerate()` to yield no results. - -To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via `CGO_ENABLED=1` and you'll need to install and set a cross compilation enabled C toolkit via `CC=your-cross-gcc`. - -## Acknowledgements - -Although the `hid` package is an implementation from scratch, it was heavily inspired by the existing -[`go.hid`](https://github.com/GeertJohan/go.hid) library, which seems abandoned since 2015; is incompatible -with Go 1.6+; and has various external dependencies. Given its inspirational roots, I thought it important -to give credit to the author of said package too. - -Wide character support in the `hid` package is done via the [`gowchar`](https://github.com/orofarne/gowchar) -library, unmaintained since 2013; non buildable with a modern Go release and failing `go vet` checks. As -such, `gowchar` was also vendored in inline (copyright headers and origins preserved). - -## License - -The components of `hid` are licensed as such: - - * `hidapi` is released under the [3-clause BSD](https://github.com/signal11/hidapi/blob/master/LICENSE-bsd.txt) license. - * `libusb` is released under the [GNU LGPL 2.1](https://github.com/libusb/libusb/blob/master/COPYING)license. - * `go.hid` is released under the [2-clause BSD](https://github.com/GeertJohan/go.hid/blob/master/LICENSE) license. - * `gowchar` is released under the [3-clause BSD](https://github.com/orofarne/gowchar/blob/master/LICENSE) license. - -Given the above, `hid` is licensed under GNU LGPL 2.1 or later on Linux and 3-clause BSD on other platforms. diff --git a/vendor/github.com/karalabe/hid/hid.go b/vendor/github.com/karalabe/hid/hid.go deleted file mode 100644 index 60a40b8c2..000000000 --- a/vendor/github.com/karalabe/hid/hid.go +++ /dev/null @@ -1,37 +0,0 @@ -// hid - Gopher Interface Devices (USB HID) -// Copyright (c) 2017 Péter Szilágyi. All rights reserved. -// -// This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under GNU LGPL 2.1 or later. - -// Package hid provides an interface for USB HID devices. -package hid - -import "errors" - -// ErrDeviceClosed is returned for operations where the device closed before or -// during the execution. -var ErrDeviceClosed = errors.New("hid: device closed") - -// ErrUnsupportedPlatform is returned for all operations where the underlying -// operating system is not supported by the library. -var ErrUnsupportedPlatform = errors.New("hid: unsupported platform") - -// DeviceInfo is a hidapi info structure. -type DeviceInfo struct { - Path string // Platform-specific device path - VendorID uint16 // Device Vendor ID - ProductID uint16 // Device Product ID - Release uint16 // Device Release Number in binary-coded decimal, also known as Device Version Number - Serial string // Serial Number - Manufacturer string // Manufacturer String - Product string // Product string - UsagePage uint16 // Usage Page for this Device/Interface (Windows/Mac only) - Usage uint16 // Usage for this Device/Interface (Windows/Mac only) - - // The USB interface which this logical device - // represents. Valid on both Linux implementations - // in all cases, and valid on the Windows implementation - // only if the device contains more than one interface. - Interface int -} diff --git a/vendor/github.com/karalabe/hid/hid_disabled.go b/vendor/github.com/karalabe/hid/hid_disabled.go deleted file mode 100644 index 0f266ba58..000000000 --- a/vendor/github.com/karalabe/hid/hid_disabled.go +++ /dev/null @@ -1,51 +0,0 @@ -// hid - Gopher Interface Devices (USB HID) -// Copyright (c) 2017 Péter Szilágyi. All rights reserved. -// -// This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under GNU LGPL 2.1 or later. - -// +build !linux,!darwin,!windows ios !cgo - -package hid - -// Supported returns whether this platform is supported by the HID library or not. -// The goal of this method is to allow programatically handling platforms that do -// not support USB HID and not having to fall back to build constraints. -func Supported() bool { - return false -} - -// Enumerate returns a list of all the HID devices attached to the system which -// match the vendor and product id. On platforms that this file implements the -// function is a noop and returns an empty list always. -func Enumerate(vendorID uint16, productID uint16) []DeviceInfo { - return nil -} - -// Device is a live HID USB connected device handle. On platforms that this file -// implements the type lacks the actual HID device and all methods are noop. -type Device struct { - DeviceInfo // Embed the infos for easier access -} - -// Open connects to an HID device by its path name. On platforms that this file -// implements the method just returns an error. -func (info DeviceInfo) Open() (*Device, error) { - return nil, ErrUnsupportedPlatform -} - -// Close releases the HID USB device handle. On platforms that this file implements -// the method is just a noop. -func (dev *Device) Close() error { return nil } - -// Write sends an output report to a HID device. On platforms that this file -// implements the method just returns an error. -func (dev *Device) Write(b []byte) (int, error) { - return 0, ErrUnsupportedPlatform -} - -// Read retrieves an input report from a HID device. On platforms that this file -// implements the method just returns an error. -func (dev *Device) Read(b []byte) (int, error) { - return 0, ErrUnsupportedPlatform -} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.c b/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.c deleted file mode 100644 index 982560751..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * poll_windows: poll compatibility wrapper for Windows - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. - * - * This 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 2.1 of the License, or (at your option) any later version. - * - * This 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* - * poll() and pipe() Windows compatibility layer for libusb 1.0 - * - * The way this layer works is by using OVERLAPPED with async I/O transfers, as - * OVERLAPPED have an associated event which is flagged for I/O completion. - * - * For USB pollable async I/O, you would typically: - * - obtain a Windows HANDLE to a file or device that has been opened in - * OVERLAPPED mode - * - call usbi_create_fd with this handle to obtain a custom fd. - * Note that if you need simultaneous R/W access, you need to call create_fd - * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate - * pollable fds - * - leave the core functions call the poll routine and flag POLLIN/POLLOUT - * - * The pipe pollable synchronous I/O works using the overlapped event associated - * with a fake pipe. The read/write functions are only meant to be used in that - * context. - */ -#include - -#include -#include -#include - -#include "libusbi.h" - -// Uncomment to debug the polling layer -//#define DEBUG_POLL_WINDOWS -#if defined(DEBUG_POLL_WINDOWS) -#define poll_dbg usbi_dbg -#else -// MSVC++ < 2005 cannot use a variadic argument and non MSVC -// compilers produce warnings if parenthesis are omitted. -#if defined(_MSC_VER) && (_MSC_VER < 1400) -#define poll_dbg -#else -#define poll_dbg(...) -#endif -#endif - -#if defined(_PREFAST_) -#pragma warning(disable:28719) -#endif - -#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) - -// public fd data -const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; -struct winfd poll_fd[MAX_FDS]; -// internal fd data -struct { - CRITICAL_SECTION mutex; // lock for fds - // Additional variables for XP CancelIoEx partial emulation - HANDLE original_handle; - DWORD thread_id; -} _poll_fd[MAX_FDS]; - -// globals -BOOLEAN is_polling_set = FALSE; -LONG pipe_number = 0; -static volatile LONG compat_spinlock = 0; - -#if !defined(_WIN32_WCE) -// CancelIoEx, available on Vista and later only, provides the ability to cancel -// a single transfer (OVERLAPPED) when used. As it may not be part of any of the -// platform headers, we hook into the Kernel32 system DLL directly to seek it. -static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; -#define Use_Duplicate_Handles (pCancelIoEx == NULL) - -static inline void setup_cancel_io(void) -{ - HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); - if (hKernel32 != NULL) { - pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) - GetProcAddress(hKernel32, "CancelIoEx"); - } - usbi_dbg("Will use CancelIo%s for I/O cancellation", - Use_Duplicate_Handles?"":"Ex"); -} - -static inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - return TRUE; - } - if (pCancelIoEx != NULL) { - return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped); - } - if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { - return CancelIo(poll_fd[_index].handle); - } - usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); - return FALSE; -} -#else -#define Use_Duplicate_Handles FALSE - -static __inline void setup_cancel_io() -{ - // No setup needed on WinCE -} - -static __inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - } - return TRUE; -} -#endif - -// Init -void init_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (!is_polling_set) { - setup_cancel_io(); - for (i=0; ihEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(overlapped->hEvent == NULL) { - free (overlapped); - return NULL; - } - return overlapped; -} - -static void free_overlapped(OVERLAPPED *overlapped) -{ - if (overlapped == NULL) - return; - - if ( (overlapped->hEvent != 0) - && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { - CloseHandle(overlapped->hEvent); - } - free(overlapped); -} - -void exit_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (is_polling_set) { - is_polling_set = FALSE; - - for (i=0; iInternal = STATUS_PENDING; - overlapped->InternalHigh = 0; - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - - // Use index as the unique fd number - poll_fd[i].fd = i; - // Read end of the "pipe" - filedes[0] = poll_fd[i].fd; - // We can use the same handle for both ends - filedes[1] = filedes[0]; - - poll_fd[i].handle = DUMMY_HANDLE; - poll_fd[i].overlapped = overlapped; - // There's no polling on the write end, so we just use READ for our needs - poll_fd[i].rw = RW_READ; - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - LeaveCriticalSection(&_poll_fd[i].mutex); - return 0; - } - } - free_overlapped(overlapped); - return -1; -} - -/* - * Create both an fd and an OVERLAPPED from an open Windows handle, so that - * it can be used with our polling function - * The handle MUST support overlapped transfers (usually requires CreateFile - * with FILE_FLAG_OVERLAPPED) - * Return a pollable file descriptor struct, or INVALID_WINFD on error - * - * Note that the fd returned by this function is a per-transfer fd, rather - * than a per-session fd and cannot be used for anything else but our - * custom functions (the fd itself points to the NUL: device) - * if you plan to do R/W on the same handle, you MUST create 2 fds: one for - * read and one for write. Using a single R/W fd is unsupported and will - * produce unexpected results - */ -struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn) -{ - int i; - struct winfd wfd = INVALID_WINFD; - OVERLAPPED* overlapped = NULL; - - CHECK_INIT_POLLING; - - if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { - return INVALID_WINFD; - } - - wfd.itransfer = itransfer; - wfd.cancel_fn = cancel_fn; - - if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { - usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. " - "If you want to poll for R/W simultaneously, create multiple fds from the same handle."); - return INVALID_WINFD; - } - if (access_mode == RW_READ) { - wfd.rw = RW_READ; - } else { - wfd.rw = RW_WRITE; - } - - overlapped = create_overlapped(); - if(overlapped == NULL) { - return INVALID_WINFD; - } - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - // Use index as the unique fd number - wfd.fd = i; - // Attempt to emulate some of the CancelIoEx behaviour on platforms - // that don't have it - if (Use_Duplicate_Handles) { - _poll_fd[i].thread_id = GetCurrentThreadId(); - if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), - &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - usbi_dbg("could not duplicate handle for CancelIo - using original one"); - wfd.handle = handle; - // Make sure we won't close the original handle on fd deletion then - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - } else { - _poll_fd[i].original_handle = handle; - } - } else { - wfd.handle = handle; - } - wfd.overlapped = overlapped; - memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); - LeaveCriticalSection(&_poll_fd[i].mutex); - return wfd; - } - } - free_overlapped(overlapped); - return INVALID_WINFD; -} - -static void _free_index(int _index) -{ - // Cancel any async IO (Don't care about the validity of our handles for this) - cancel_io(_index); - // close the duplicate handle (if we have an actual duplicate) - if (Use_Duplicate_Handles) { - if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { - CloseHandle(poll_fd[_index].handle); - } - _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; - _poll_fd[_index].thread_id = 0; - } - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; -} - -/* - * Release a pollable file descriptor. - * - * Note that the associated Windows handle is not closed by this call - */ -void usbi_free_fd(struct winfd *wfd) -{ - int _index; - - CHECK_INIT_POLLING; - - _index = _fd_to_index_and_lock(wfd->fd); - if (_index < 0) { - return; - } - _free_index(_index); - *wfd = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); -} - -/* - * The functions below perform various conversions between fd, handle and OVERLAPPED - */ -struct winfd fd_to_winfd(int fd) -{ - int i; - struct winfd wfd; - - CHECK_INIT_POLLING; - - if (fd < 0) - return INVALID_WINFD; - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - usbi_warn(NULL, "invalid fd"); - triggered = -1; - goto poll_exit; - } - - // IN or OUT must match our fd direction - if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLIN on fd without READ access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - // The following macro only works if overlapped I/O was reported pending - if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped)) - || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) { - poll_dbg(" completed"); - // checks above should ensure this works: - fds[i].revents = fds[i].events; - triggered++; - } else { - handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent; - handle_to_index[nb_handles_to_wait_on] = i; - nb_handles_to_wait_on++; - } - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - - // If nothing was triggered, wait on all fds that require it - if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { - if (timeout < 0) { - poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on); - } else { - poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on); - } - ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, - FALSE, (timeout<0)?INFINITE:(DWORD)timeout); - object_index = ret-WAIT_OBJECT_0; - if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) { - poll_dbg(" completed after wait"); - i = handle_to_index[object_index]; - _index = _fd_to_index_and_lock(fds[i].fd); - fds[i].revents = fds[i].events; - triggered++; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - } else if (ret == WAIT_TIMEOUT) { - poll_dbg(" timed out"); - triggered = 0; // 0 = timeout - } else { - errno = EIO; - triggered = -1; // error - } - } - -poll_exit: - if (handles_to_wait_on != NULL) { - free(handles_to_wait_on); - } - if (handle_to_index != NULL) { - free(handle_to_index); - } - return triggered; -} - -/* - * close a fake pipe fd - */ -int usbi_close(int fd) -{ - int _index; - int r = -1; - - CHECK_INIT_POLLING; - - _index = _fd_to_index_and_lock(fd); - - if (_index < 0) { - errno = EBADF; - } else { - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - return r; -} - -/* - * synchronous write for fake "pipe" signaling - */ -ssize_t usbi_write(int fd, const void *buf, size_t count) -{ - int _index; - UNUSED(buf); - - CHECK_INIT_POLLING; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - return -1; - } - - _index = _fd_to_index_and_lock(fd); - - if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { - errno = EBADF; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - return -1; - } - - poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - SetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_WAIT_0; - // If two threads write on the pipe at the same time, we need to - // process two separate reads => use the overlapped as a counter - poll_fd[_index].overlapped->InternalHigh++; - - LeaveCriticalSection(&_poll_fd[_index].mutex); - return sizeof(unsigned char); -} - -/* - * synchronous read for fake "pipe" signaling - */ -ssize_t usbi_read(int fd, void *buf, size_t count) -{ - int _index; - ssize_t r = -1; - UNUSED(buf); - - CHECK_INIT_POLLING; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - return -1; - } - - _index = _fd_to_index_and_lock(fd); - - if (_index < 0) { - errno = EBADF; - return -1; - } - - if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { - usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError()); - errno = EIO; - goto out; - } - - poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - poll_fd[_index].overlapped->InternalHigh--; - // Don't reset unless we don't have any more events to process - if (poll_fd[_index].overlapped->InternalHigh <= 0) { - ResetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_PENDING; - } - - r = sizeof(unsigned char); - -out: - LeaveCriticalSection(&_poll_fd[_index].mutex); - return r; -} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.h b/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.h deleted file mode 100644 index 4c1514ea6..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * libusb synchronization using POSIX Threads - * - * Copyright © 2010 Peter Stuge - * - * This 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 2.1 of the License, or (at your option) any later version. - * - * This 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_THREADS_POSIX_H -#define LIBUSB_THREADS_POSIX_H - -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#define usbi_mutex_static_t pthread_mutex_t -#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#define usbi_mutex_static_lock pthread_mutex_lock -#define usbi_mutex_static_unlock pthread_mutex_unlock - -#define usbi_mutex_t pthread_mutex_t -#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL) -#define usbi_mutex_lock pthread_mutex_lock -#define usbi_mutex_unlock pthread_mutex_unlock -#define usbi_mutex_trylock pthread_mutex_trylock -#define usbi_mutex_destroy pthread_mutex_destroy - -#define usbi_cond_t pthread_cond_t -#define usbi_cond_init(cond) pthread_cond_init((cond), NULL) -#define usbi_cond_wait pthread_cond_wait -#define usbi_cond_broadcast pthread_cond_broadcast -#define usbi_cond_destroy pthread_cond_destroy - -#define usbi_tls_key_t pthread_key_t -#define usbi_tls_key_create(key) pthread_key_create((key), NULL) -#define usbi_tls_key_get pthread_getspecific -#define usbi_tls_key_set pthread_setspecific -#define usbi_tls_key_delete pthread_key_delete - -int usbi_get_tid(void); - -#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.c b/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.c deleted file mode 100644 index 7c2e52dba..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * libusb synchronization on Microsoft Windows - * - * Copyright © 2010 Michael Plante - * - * This 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 2.1 of the License, or (at your option) any later version. - * - * This 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include "libusbi.h" - -struct usbi_cond_perthread { - struct list_head list; - DWORD tid; - HANDLE event; -}; - -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) -{ - if (!mutex) - return EINVAL; - while (InterlockedExchange(mutex, 1) == 1) - SleepEx(0, TRUE); - return 0; -} - -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) -{ - if (!mutex) - return EINVAL; - InterlockedExchange(mutex, 0); - return 0; -} - -int usbi_mutex_init(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - *mutex = CreateMutex(NULL, FALSE, NULL); - if (!*mutex) - return ENOMEM; - return 0; -} - -int usbi_mutex_lock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, INFINITE); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else - return EINVAL; // don't know how this would happen - // so don't know proper errno -} - -int usbi_mutex_unlock(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - if (ReleaseMutex(*mutex)) - return 0; - else - return EPERM; -} - -int usbi_mutex_trylock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, 0); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else if (result == WAIT_TIMEOUT) - return EBUSY; - else - return EINVAL; // don't know how this would happen - // so don't know proper error -} - -int usbi_mutex_destroy(usbi_mutex_t *mutex) -{ - // It is not clear if CloseHandle failure is due to failure to unlock. - // If so, this should be errno=EBUSY. - if (!mutex || !CloseHandle(*mutex)) - return EINVAL; - *mutex = NULL; - return 0; -} - -int usbi_cond_init(usbi_cond_t *cond) -{ - if (!cond) - return EINVAL; - list_init(&cond->waiters); - list_init(&cond->not_waiting); - return 0; -} - -int usbi_cond_destroy(usbi_cond_t *cond) -{ - // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next_pos; - - if(!cond) - return EINVAL; - if (!list_empty(&cond->waiters)) - return EBUSY; // (!see above!) - list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - CloseHandle(pos->event); - list_del(&pos->list); - free(pos); - } - return 0; -} - -int usbi_cond_broadcast(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - int fail = 0; - struct usbi_cond_perthread *pos; - - if (!cond) - return EINVAL; - list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { - if (!SetEvent(pos->event)) - fail = 1; - } - // The wait function will remove its respective item from the list. - return fail ? EINVAL : 0; -} - -__inline static int usbi_cond_intwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, DWORD timeout_ms) -{ - struct usbi_cond_perthread *pos; - int r, found = 0; - DWORD r2, tid = GetCurrentThreadId(); - - if (!cond || !mutex) - return EINVAL; - list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - if(tid == pos->tid) { - found = 1; - break; - } - } - - if (!found) { - pos = calloc(1, sizeof(struct usbi_cond_perthread)); - if (!pos) - return ENOMEM; // This errno is not POSIX-allowed. - pos->tid = tid; - pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if (!pos->event) { - free(pos); - return ENOMEM; - } - list_add(&pos->list, &cond->not_waiting); - } - - list_del(&pos->list); // remove from not_waiting list. - list_add(&pos->list, &cond->waiters); - - r = usbi_mutex_unlock(mutex); - if (r) - return r; - - r2 = WaitForSingleObject(pos->event, timeout_ms); - r = usbi_mutex_lock(mutex); - if (r) - return r; - - list_del(&pos->list); - list_add(&pos->list, &cond->not_waiting); - - if (r2 == WAIT_OBJECT_0) - return 0; - else if (r2 == WAIT_TIMEOUT) - return ETIMEDOUT; - else - return EINVAL; -} -// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) -{ - return usbi_cond_intwait(cond, mutex, INFINITE); -} - -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv) -{ - DWORD millis; - - millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); - /* round up to next millisecond */ - if (tv->tv_usec % 1000) - millis++; - return usbi_cond_intwait(cond, mutex, millis); -} - -int usbi_tls_key_create(usbi_tls_key_t *key) -{ - if (!key) - return EINVAL; - *key = TlsAlloc(); - if (*key == TLS_OUT_OF_INDEXES) - return ENOMEM; - else - return 0; -} - -void *usbi_tls_key_get(usbi_tls_key_t key) -{ - return TlsGetValue(key); -} - -int usbi_tls_key_set(usbi_tls_key_t key, void *value) -{ - if (TlsSetValue(key, value)) - return 0; - else - return EINVAL; -} - -int usbi_tls_key_delete(usbi_tls_key_t key) -{ - if (TlsFree(key)) - return 0; - else - return EINVAL; -} - -int usbi_get_tid(void) -{ - return (int)GetCurrentThreadId(); -} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.h b/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.h deleted file mode 100644 index 52ea8708b..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Windows backend common header for libusb 1.0 - * - * This file brings together header code common between - * the desktop Windows backends. - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This 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 2.1 of the License, or (at your option) any later version. - * - * This 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -// Missing from MinGW -#if !defined(FACILITY_SETUPAPI) -#define FACILITY_SETUPAPI 15 -#endif - -typedef struct USB_CONFIGURATION_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wTotalLength; - UCHAR bNumInterfaces; - UCHAR bConfigurationValue; - UCHAR iConfiguration; - UCHAR bmAttributes; - UCHAR MaxPower; -} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; - -typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; - -int windows_common_init(struct libusb_context *ctx); -void windows_common_exit(void); - -unsigned long htab_hash(const char *str); -int windows_clock_gettime(int clk_id, struct timespec *tp); - -void windows_clear_transfer_priv(struct usbi_transfer *itransfer); -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size); -struct winfd *windows_get_fd(struct usbi_transfer *transfer); -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size); - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size); -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); - -#if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD error_code); -#endif diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.c b/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.c deleted file mode 100644 index 0dce0ea6c..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.c +++ /dev/null @@ -1,4290 +0,0 @@ -/* - * windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software - * Hash table functions adapted from glibc, by Ulrich Drepper et al. - * Major code testing contribution by Xiaofan Chen - * - * This 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 2.1 of the License, or (at your option) any later version. - * - * This 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#if !defined(USE_USBDK) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "poll_windows.h" -#include "windows_winusb.h" - -#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE)) - -// The 2 macros below are used in conjunction with safe loops. -#define LOOP_CHECK(fcall) \ - { \ - r = fcall; \ - if (r != LIBUSB_SUCCESS) \ - continue; \ - } -#define LOOP_BREAK(err) \ - { \ - r = err; \ - continue; \ - } - -// WinUSB-like API prototypes -static int winusbx_init(int sub_api, struct libusb_context *ctx); -static int winusbx_exit(int sub_api); -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -// HID API prototypes -static int hid_init(int sub_api, struct libusb_context *ctx); -static int hid_exit(int sub_api); -static int hid_open(int sub_api, struct libusb_device_handle *dev_handle); -static void hid_close(int sub_api, struct libusb_device_handle *dev_handle); -static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -// Composite API prototypes -static int composite_init(int sub_api, struct libusb_context *ctx); -static int composite_exit(int sub_api); -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); - - -// Global variables -int windows_version = WINDOWS_UNDEFINED; -static char windows_version_str[128] = "Undefined"; -// Concurrency -static int concurrent_usage = -1; -static usbi_mutex_t autoclaim_lock; -// API globals -#define CHECK_WINUSBX_AVAILABLE(sub_api) \ - do { \ - if (sub_api == SUB_API_NOTSET) \ - sub_api = priv->sub_api; \ - if (!WinUSBX[sub_api].initialized) \ - return LIBUSB_ERROR_ACCESS; \ - } while(0) - -static HMODULE WinUSBX_handle = NULL; -static struct winusb_interface WinUSBX[SUB_API_MAX]; -static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; - -static bool api_hid_available = false; -#define CHECK_HID_AVAILABLE \ - do { \ - if (!api_hid_available) \ - return LIBUSB_ERROR_ACCESS; \ - } while (0) - -static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) -{ - if ((guid1 != NULL) && (guid2 != NULL)) - return (memcmp(guid1, guid2, sizeof(GUID)) == 0); - - return false; -} - -#if defined(ENABLE_LOGGING) -static char *guid_to_string(const GUID *guid) -{ - static char guid_string[MAX_GUID_STRING_LENGTH]; - - if (guid == NULL) - return NULL; - - sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - (unsigned int)guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); - - return guid_string; -} -#endif - -/* - * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. - * Return an allocated sanitized string or NULL on error. - */ -static char *sanitize_path(const char *path) -{ - const char root_prefix[] = { '\\', '\\', '.', '\\' }; - size_t j, size; - char *ret_path; - size_t add_root = 0; - - if (path == NULL) - return NULL; - - size = strlen(path) + 1; - - // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. - if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) - || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { - add_root = sizeof(root_prefix); - size += add_root; - } - - ret_path = malloc(size); - if (ret_path == NULL) - return NULL; - - strcpy(&ret_path[add_root], path); - - // Ensure consistency with root prefix - memcpy(ret_path, root_prefix, sizeof(root_prefix)); - - // Same goes for '\' and '#' after the root prefix. Ensure '#' is used - for (j = sizeof(root_prefix); j < size; j++) { - ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too - if (ret_path[j] == '\\') - ret_path[j] = '#'; - } - - return ret_path; -} - -/* - * Cfgmgr32, OLE32 and SetupAPI DLL functions - */ -static int init_dlls(void) -{ - DLL_GET_HANDLE(Cfgmgr32); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE); - - // Prefixed to avoid conflict with header files - DLL_GET_HANDLE(AdvAPI32); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); - - DLL_GET_HANDLE(Kernel32); - DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); - - DLL_GET_HANDLE(OLE32); - DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE); - - DLL_GET_HANDLE(SetupAPI); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - - return LIBUSB_SUCCESS; -} - -static void exit_dlls(void) -{ - DLL_FREE_HANDLE(Cfgmgr32); - DLL_FREE_HANDLE(AdvAPI32); - DLL_FREE_HANDLE(Kernel32); - DLL_FREE_HANDLE(OLE32); - DLL_FREE_HANDLE(SetupAPI); -} - -/* - * enumerate interfaces for the whole USB class - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * usb_class: the generic USB class for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static bool get_devinfo_data(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index) -{ - if (_index <= 0) { - *dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); - if (*dev_info == INVALID_HANDLE_VALUE) - return false; - } - - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return false; - } - return true; -} - -/* - * enumerate interfaces for a specific GUID - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * guid: the GUID for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; - DWORD size; - - if (_index <= 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; - } - - dev_interface_details = calloc(1, size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, - dev_interface_details, size, &size, NULL)) { - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); - } - - return dev_interface_details; - -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; -} - -/* For libusb0 filter */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; - DWORD size; - - if (_index <= 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; - } - - dev_interface_details = calloc(1, size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); - - // [trobinso] lookup the libusb0 symbolic index. - if (dev_interface_details) { - HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); - if (hkey_device_interface != INVALID_HANDLE_VALUE) { - DWORD libusb0_symboliclink_index = 0; - DWORD value_length = sizeof(DWORD); - DWORD value_type = 0; - LONG status; - - status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, - (LPBYTE)&libusb0_symboliclink_index, &value_length); - if (status == ERROR_SUCCESS) { - if (libusb0_symboliclink_index < 256) { - // libusb0.sys is connected to this device instance. - // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. - sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); - usbi_dbg("assigned libusb0 symbolic link %s", filter_path); - } else { - // libusb0.sys was connected to this device instance at one time; but not anymore. - } - } - pRegCloseKey(hkey_device_interface); - } - } - - return dev_interface_details; - -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; -} - -/* - * Returns the session ID of a device's nth level ancestor - * If there's no device at the nth level, return 0 - */ -static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level) -{ - DWORD parent_devinst; - unsigned long session_id; - char *sanitized_path; - char path[MAX_PATH_LENGTH]; - unsigned i; - - if (level < 1) - return 0; - - for (i = 0; i < level; i++) { - if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) - return 0; - devinst = parent_devinst; - } - - if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) - return 0; - - // TODO: (post hotplug): try without sanitizing - sanitized_path = sanitize_path(path); - if (sanitized_path == NULL) - return 0; - - session_id = htab_hash(sanitized_path); - free(sanitized_path); - return session_id; -} - -/* - * Determine which interface the given endpoint address belongs to - */ -static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep) -{ - const struct libusb_interface *intf; - const struct libusb_interface_descriptor *intf_desc; - int i, j, k; - - for (i = 0; i < conf_desc->bNumInterfaces; i++) { - intf = &conf_desc->interface[i]; - for (j = 0; j < intf->num_altsetting; j++) { - intf_desc = &intf->altsetting[j]; - for (k = 0; k < intf_desc->bNumEndpoints; k++) { - if (intf_desc->endpoint[k].bEndpointAddress == ep) { - usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i); - return intf_desc->bInterfaceNumber; - } - } - } - } - - usbi_dbg("endpoint %02X not found on any interface", ep); - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * Populate the endpoints addresses of the device_priv interface helper structs - */ -static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - int i, r; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - const struct libusb_interface_descriptor *if_desc; - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); - if (r != LIBUSB_SUCCESS) { - usbi_warn(ctx, "could not read config descriptor: error %d", r); - return r; - } - - if_desc = &conf_desc->interface[iface].altsetting[altsetting]; - safe_free(priv->usb_interface[iface].endpoint); - - if (if_desc->bNumEndpoints == 0) { - usbi_dbg("no endpoints found for interface %d", iface); - libusb_free_config_descriptor(conf_desc); - return LIBUSB_SUCCESS; - } - - priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); - if (priv->usb_interface[iface].endpoint == NULL) { - libusb_free_config_descriptor(conf_desc); - return LIBUSB_ERROR_NO_MEM; - } - - priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; - for (i = 0; i < if_desc->bNumEndpoints; i++) { - priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; - usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); - } - libusb_free_config_descriptor(conf_desc); - - // Extra init may be required to configure endpoints - return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); -} - -// Lookup for a match in the list of API driver names -// return -1 if not found, driver match number otherwise -static int get_sub_api(char *driver, int api) -{ - int i; - const char sep_str[2] = {LIST_SEPARATOR, 0}; - char *tok, *tmp_str; - size_t len = strlen(driver); - - if (len == 0) - return SUB_API_NOTSET; - - tmp_str = _strdup(driver); - if (tmp_str == NULL) - return SUB_API_NOTSET; - - tok = strtok(tmp_str, sep_str); - while (tok != NULL) { - for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { - if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { - free(tmp_str); - return i; - } - } - tok = strtok(NULL, sep_str); - } - - free(tmp_str); - return SUB_API_NOTSET; -} - -/* - * auto-claiming and auto-release helper functions - */ -static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) -{ - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv( - transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = *interface_number; - int r = LIBUSB_SUCCESS; - - switch(api_type) { - case USB_API_WINUSBX: - case USB_API_HID: - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_mutex_lock(&autoclaim_lock); - if (current_interface < 0) { // No serviceable interface was found - for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { - // Must claim an interface of the same API type - if ((priv->usb_interface[current_interface].apib->id == api_type) - && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { - usbi_dbg("auto-claimed interface %d for control request", current_interface); - if (handle_priv->autoclaim_count[current_interface] != 0) - usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); - handle_priv->autoclaim_count[current_interface]++; - break; - } - } - if (current_interface == USB_MAXINTERFACES) { - usbi_err(ctx, "could not auto-claim any interface"); - r = LIBUSB_ERROR_NOT_FOUND; - } - } else { - // If we have a valid interface that was autoclaimed, we must increment - // its autoclaim count so that we can prevent an early release. - if (handle_priv->autoclaim_count[current_interface] != 0) - handle_priv->autoclaim_count[current_interface]++; - } - usbi_mutex_unlock(&autoclaim_lock); - - *interface_number = current_interface; - return r; -} - -static void auto_release(struct usbi_transfer *itransfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - libusb_device_handle *dev_handle = transfer->dev_handle; - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - int r; - - usbi_mutex_lock(&autoclaim_lock); - if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) { - handle_priv->autoclaim_count[transfer_priv->interface_number]--; - if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { - r = libusb_release_interface(dev_handle, transfer_priv->interface_number); - if (r == LIBUSB_SUCCESS) - usbi_dbg("auto-released interface %d", transfer_priv->interface_number); - else - usbi_dbg("failed to auto-release interface %d (%s)", - transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); - } - } - usbi_mutex_unlock(&autoclaim_lock); -} - -/* Windows version dtection */ -static BOOL is_x64(void) -{ - BOOL ret = FALSE; - - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - if (pIsWow64Process != NULL) - pIsWow64Process(GetCurrentProcess(), &ret); - } else { - ret = TRUE; - } - - return ret; -} - -static void get_windows_version(void) -{ - OSVERSIONINFOEXA vi, vi2; - const char *arch, *w = NULL; - unsigned major, minor; - ULONGLONG major_equal, minor_equal; - BOOL ws; - - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) - return; - } - - if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { - if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { - // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version - // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx - - major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - for (major = vi.dwMajorVersion; major <= 9; major++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMajorVersion = major; - if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) - continue; - - if (vi.dwMajorVersion < major) { - vi.dwMajorVersion = major; - vi.dwMinorVersion = 0; - } - - minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); - for (minor = vi.dwMinorVersion; minor <= 9; minor++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMinorVersion = minor; - if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) - continue; - - vi.dwMinorVersion = minor; - break; - } - - break; - } - } - - if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { - ws = (vi.wProductType <= VER_NT_WORKSTATION); - windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; - switch (windows_version) { - case 0x50: w = "2000"; break; - case 0x51: w = "XP"; break; - case 0x52: w = "2003"; break; - case 0x60: w = (ws ? "Vista" : "2008"); break; - case 0x61: w = (ws ? "7" : "2008_R2"); break; - case 0x62: w = (ws ? "8" : "2012"); break; - case 0x63: w = (ws ? "8.1" : "2012_R2"); break; - case 0x64: w = (ws ? "10" : "2015"); break; - default: - if (windows_version < 0x50) - windows_version = WINDOWS_UNSUPPORTED; - else - w = "11 or later"; - break; - } - } - } - - arch = is_x64() ? "64-bit" : "32-bit"; - - if (w == NULL) - snprintf(windows_version_str, sizeof(windows_version_str), "%s %u.%u %s", - (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), - (unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, arch); - else if (vi.wServicePackMinor) - snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u.%u %s", - w, vi.wServicePackMajor, vi.wServicePackMinor, arch); - else if (vi.wServicePackMajor) - snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u %s", - w, vi.wServicePackMajor, arch); - else - snprintf(windows_version_str, sizeof(windows_version_str), "%s %s", - w, arch); -} - -/* - * init: libusb backend init function - * - * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list - * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed. - * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?) - */ -static int windows_init(struct libusb_context *ctx) -{ - int i, r = LIBUSB_ERROR_OTHER; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; - } - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if (++concurrent_usage == 0) { // First init? - get_windows_version(); - usbi_dbg("Windows %s", windows_version_str); - - if (windows_version == WINDOWS_UNSUPPORTED) { - usbi_err(ctx, "This version of Windows is NOT supported"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // We need a lock for proper auto-release - usbi_mutex_init(&autoclaim_lock); - - // Initialize pollable file descriptors - init_polling(); - - // Load DLL imports - if (init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - goto init_exit; - } - - // Initialize the low level APIs (we don't care about errors at this stage) - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].init(SUB_API_NOTSET, ctx); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here. - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -/* - * HCD (root) hubs need to have their device descriptor manually populated - * - * Note that, like Microsoft does in the device manager, we populate the - * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device. - */ -static int force_hcd_device_descriptor(struct libusb_device *dev) -{ - struct windows_device_priv *parent_priv, *priv = _device_priv(dev); - struct libusb_context *ctx = DEVICE_CTX(dev); - int vid, pid; - - dev->num_configurations = 1; - priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR); - priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - priv->dev_descriptor.bNumConfigurations = 1; - priv->active_config = 1; - - if (dev->parent_dev == NULL) { - usbi_err(ctx, "program assertion failed - HCD hub has no parent"); - return LIBUSB_ERROR_NO_DEVICE; - } - - parent_priv = _device_priv(dev->parent_dev); - if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) { - priv->dev_descriptor.idVendor = (uint16_t)vid; - priv->dev_descriptor.idProduct = (uint16_t)pid; - } else { - usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path); - priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub - priv->dev_descriptor.idProduct = 1; - } - - return LIBUSB_SUCCESS; -} - -/* - * fetch and cache all the config descriptors through I/O - */ -static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id) -{ - DWORD size, ret_size; - struct libusb_context *ctx = DEVICE_CTX(dev); - struct windows_device_priv *priv = _device_priv(dev); - int r; - uint8_t i; - - USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request - PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request - PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL; - - if (dev->num_configurations == 0) - return LIBUSB_ERROR_INVALID_PARAM; - - priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *)); - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NO_MEM; - - for (i = 0; i < dev->num_configurations; i++) - priv->config_descriptor[i] = NULL; - - for (i = 0, r = LIBUSB_SUCCESS; ; i++) { - // safe loop: release all dynamic resources - safe_free(cd_buf_actual); - - // safe loop: end of loop condition - if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS)) - break; - - size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT); - memset(&cd_buf_short, 0, size); - - cd_buf_short.req.ConnectionIndex = (ULONG)priv->port; - cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; - cd_buf_short.req.SetupPacket.wIndex = 0; - cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Dummy call to get the required data size. Initial failures are reported as info rather - // than error as they can occur for non-penalizing situations, such as with some hubs. - // coverity[tainted_data_argument] - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, - &cd_buf_short, size, &ret_size, NULL)) { - usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { - usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength; - cd_buf_actual = calloc(1, size); - if (cd_buf_actual == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - - // Actual call - cd_buf_actual->ConnectionIndex = (ULONG)priv->port; - cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; - cd_buf_actual->SetupPacket.wIndex = 0; - cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); - - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, - cd_buf_actual, size, &ret_size, NULL)) { - usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); - - if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) { - usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) { - usbi_err(ctx, "not a configuration descriptor for '%s'", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)", - i, cd_data->bConfigurationValue, cd_data->wTotalLength); - - // Cache the descriptor - priv->config_descriptor[i] = malloc(cd_data->wTotalLength); - if (priv->config_descriptor[i] == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); - } - return LIBUSB_SUCCESS; -} - -/* - * Populate a libusb device structure - */ -static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, - uint8_t port_number, char *device_id, DWORD devinst) -{ - HANDLE handle; - DWORD size; - USB_NODE_CONNECTION_INFORMATION_EX conn_info; - USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; - struct windows_device_priv *priv, *parent_priv; - struct libusb_context *ctx; - struct libusb_device *tmp_dev; - unsigned long tmp_id; - unsigned i; - - if ((dev == NULL) || (parent_dev == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - ctx = DEVICE_CTX(dev); - priv = _device_priv(dev); - parent_priv = _device_priv(parent_dev); - if (parent_priv->apib->id != USB_API_HUB) { - usbi_warn(ctx, "parent for device '%s' is not a hub", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - // It is possible for the parent hub not to have been initialized yet - // If that's the case, lookup the ancestors to set the bus number - if (parent_dev->bus_number == 0) { - for (i = 2; ; i++) { - tmp_id = get_ancestor_session_id(devinst, i); - if (tmp_id == 0) - break; - - tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id); - if (tmp_dev == NULL) - continue; - - if (tmp_dev->bus_number != 0) { - usbi_dbg("got bus number from ancestor #%u", i); - parent_dev->bus_number = tmp_dev->bus_number; - libusb_unref_device(tmp_dev); - break; - } - - libusb_unref_device(tmp_dev); - } - } - - if (parent_dev->bus_number == 0) { - usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - dev->bus_number = parent_dev->bus_number; - priv->port = port_number; - dev->port_number = port_number; - priv->depth = parent_priv->depth + 1; - dev->parent_dev = parent_dev; - - // If the device address is already set, we can stop here - if (dev->device_address != 0) - return LIBUSB_SUCCESS; - - memset(&conn_info, 0, sizeof(conn_info)); - if (priv->depth != 0) { // Not a HCD hub - handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - if (handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - - size = sizeof(conn_info); - conn_info.ConnectionIndex = (ULONG)port_number; - // coverity[tainted_data_argument] - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size, - &conn_info, size, &size, NULL)) { - usbi_warn(ctx, "could not get node connection information for device '%s': %s", - device_id, windows_error_str(0)); - CloseHandle(handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "device '%s' is no longer connected!", device_id); - CloseHandle(handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); - dev->num_configurations = priv->dev_descriptor.bNumConfigurations; - priv->active_config = conn_info.CurrentConfigurationValue; - usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); - - // If we can't read the config descriptors, just set the number of confs to zero - if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) { - dev->num_configurations = 0; - priv->dev_descriptor.bNumConfigurations = 0; - } - - // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 - if (windows_version >= WINDOWS_8) { - memset(&conn_info_v2, 0, sizeof(conn_info_v2)); - size = sizeof(conn_info_v2); - conn_info_v2.ConnectionIndex = (ULONG)port_number; - conn_info_v2.Length = size; - conn_info_v2.SupportedUsbProtocols.Usb300 = 1; - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, - &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) { - usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", - device_id, windows_error_str(0)); - } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { - conn_info.Speed = 3; - } - } - - CloseHandle(handle); - - if (conn_info.DeviceAddress > UINT8_MAX) - usbi_err(ctx, "program assertion failed: device address overflow"); - - dev->device_address = (uint8_t)conn_info.DeviceAddress + 1; - if (dev->device_address == 1) - usbi_err(ctx, "program assertion failed: device address collision with root hub"); - - switch (conn_info.Speed) { - case 0: dev->speed = LIBUSB_SPEED_LOW; break; - case 1: dev->speed = LIBUSB_SPEED_FULL; break; - case 2: dev->speed = LIBUSB_SPEED_HIGH; break; - case 3: dev->speed = LIBUSB_SPEED_SUPER; break; - default: - usbi_warn(ctx, "Got unknown device speed %u", conn_info.Speed); - break; - } - } else { - dev->device_address = 1; // root hubs are set to use device number 1 - force_hcd_device_descriptor(dev); - } - - usbi_sanitize_device(dev); - - usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", - dev->bus_number, dev->device_address, priv->depth, priv->port, device_id); - - return LIBUSB_SUCCESS; -} - -// Returns the api type, or 0 if not found/unsupported -static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, - SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) -{ - // Precedence for filter drivers vs driver is in the order of this array - struct driver_lookup lookup[3] = { - {"\0\0", SPDRP_SERVICE, "driver"}, - {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"}, - {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"} - }; - DWORD size, reg_type; - unsigned k, l; - int i, j; - - *api = USB_API_UNSUPPORTED; - *sub_api = SUB_API_NOTSET; - - // Check the service & filter names to know the API we should use - for (k = 0; k < 3; k++) { - if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, - ®_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) { - // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ - if (lookup[k].reg_prop == SPDRP_SERVICE) - // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed - lookup[k].list[strlen(lookup[k].list) + 1] = 0; - - // MULTI_SZ is a pain to work with. Turn it into something much more manageable - // NB: none of the driver names we check against contain LIST_SEPARATOR, - // (currently ';'), so even if an unsuported one does, it's not an issue - for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { - if (lookup[k].list[l] == 0) - lookup[k].list[l] = LIST_SEPARATOR; - } - usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); - } else { - if (GetLastError() != ERROR_INVALID_DATA) - usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); - lookup[k].list[0] = 0; - } - } - - for (i = 1; i < USB_API_MAX; i++) { - for (k = 0; k < 3; k++) { - j = get_sub_api(lookup[k].list, i); - if (j >= 0) { - usbi_dbg("matched %s name against %s", lookup[k].designation, - (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]); - *api = i; - *sub_api = j; - return; - } - } - } -} - -static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path, char *device_id, int api, int sub_api) -{ - unsigned i; - struct windows_device_priv *priv = _device_priv(dev); - int interface_number; - - if (priv->apib->id != USB_API_COMPOSITE) { - usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id); - return LIBUSB_ERROR_NO_DEVICE; - } - - // Because MI_## are not necessarily in sequential order (some composite - // devices will have only MI_00 & MI_03 for instance), we retrieve the actual - // interface number from the path's MI value - interface_number = 0; - for (i = 0; device_id[i] != 0; ) { - if ((device_id[i++] == 'M') && (device_id[i++] == 'I') - && (device_id[i++] == '_')) { - interface_number = (device_id[i++] - '0') * 10; - interface_number += device_id[i] - '0'; - break; - } - } - - if (device_id[i] == 0) - usbi_warn(ctx, "failure to read interface number for %s. Using default value %d", - device_id, interface_number); - - if (priv->usb_interface[interface_number].path != NULL) { - if (api == USB_API_HID) { - // HID devices can have multiple collections (COL##) for each MI_## interface - usbi_dbg("interface[%d] already set - ignoring HID collection: %s", - interface_number, device_id); - return LIBUSB_ERROR_ACCESS; - } - // In other cases, just use the latest data - safe_free(priv->usb_interface[interface_number].path); - } - - usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); - priv->usb_interface[interface_number].path = dev_interface_path; - priv->usb_interface[interface_number].apib = &usb_api_backend[api]; - priv->usb_interface[interface_number].sub_api = sub_api; - if ((api == USB_API_HID) && (priv->hid == NULL)) { - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - return LIBUSB_ERROR_NO_MEM; - } - - return LIBUSB_SUCCESS; -} - -static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path) -{ - int i; - struct windows_device_priv *priv = _device_priv(dev); - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed: parent is not HID"); - return LIBUSB_ERROR_NO_DEVICE; - } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { - usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); - return LIBUSB_ERROR_NO_DEVICE; - } - - for (i = 0; i < priv->hid->nb_interfaces; i++) { - if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { - usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); - return LIBUSB_ERROR_ACCESS; - } - } - - priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; - priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; - usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path); - priv->hid->nb_interfaces++; - return LIBUSB_SUCCESS; -} - -/* - * get_device_list: libusb backend device enumeration function - */ -static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) -{ - struct discovered_devs *discdevs; - HDEVINFO dev_info = { 0 }; - const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"}; - SP_DEVINFO_DATA dev_info_data = { 0 }; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - GUID hid_guid; -#define MAX_ENUM_GUIDS 64 - const GUID *guid[MAX_ENUM_GUIDS]; -#define HCD_PASS 0 -#define HUB_PASS 1 -#define GEN_PASS 2 -#define DEV_PASS 3 -#define HID_PASS 4 - int r = LIBUSB_SUCCESS; - int api, sub_api; - size_t class_index = 0; - unsigned int nb_guids, pass, i, j, ancestor; - char path[MAX_PATH_LENGTH]; - char strbuf[MAX_PATH_LENGTH]; - struct libusb_device *dev, *parent_dev; - struct windows_device_priv *priv, *parent_priv; - char *dev_interface_path = NULL; - char *dev_id_path = NULL; - unsigned long session_id; - DWORD size, reg_type, port_nr, install_state; - HKEY key; - WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; - GUID *if_guid; - LONG s; - // Keep a list of newly allocated devs to unref - libusb_device **unref_list, **new_unref_list; - unsigned int unref_size = 64; - unsigned int unref_cur = 0; - - // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) - // PASS 2 : (re)enumerate HUBS - // PASS 3 : (re)enumerate generic USB devices (including driverless) - // and list additional USB device interface GUIDs to explore - // PASS 4 : (re)enumerate master USB devices that have a device interface - // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and - // set the device interfaces. - - // Init the GUID table - guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; - guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; - guid[GEN_PASS] = NULL; - guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; - HidD_GetHidGuid(&hid_guid); - guid[HID_PASS] = &hid_guid; - nb_guids = HID_PASS + 1; - - unref_list = calloc(unref_size, sizeof(libusb_device *)); - if (unref_list == NULL) - return LIBUSB_ERROR_NO_MEM; - - for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { -//#define ENUM_DEBUG -#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) - const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; - usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)], - (pass != GEN_PASS) ? guid_to_string(guid[pass]) : ""); -#endif - for (i = 0; ; i++) { - // safe loop: free up any (unprotected) dynamic resource - // NB: this is always executed before breaking the loop - safe_free(dev_interface_details); - safe_free(dev_interface_path); - safe_free(dev_id_path); - priv = parent_priv = NULL; - dev = parent_dev = NULL; - - // Safe loop: end of loop conditions - if (r != LIBUSB_SUCCESS) - break; - - if ((pass == HCD_PASS) && (i == UINT8_MAX)) { - usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX); - break; - } - - if (pass != GEN_PASS) { - // Except for GEN, all passes deal with device interfaces - dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i); - if (dev_interface_details == NULL) - break; - - dev_interface_path = sanitize_path(dev_interface_details->DevicePath); - if (dev_interface_path == NULL) { - usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath); - continue; - } - } else { - // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are - // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". - // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" - // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" - for (; class_index < ARRAYSIZE(usb_class); class_index++) { - if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i)) - break; - i = 0; - } - if (class_index >= ARRAYSIZE(usb_class)) - break; - } - - // Read the Device ID path. This is what we'll use as UID - // Note that if the device is plugged in a different port or hub, the Device ID changes - if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) { - usbi_warn(ctx, "could not read the device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); - continue; - } - - dev_id_path = sanitize_path(path); - if (dev_id_path == NULL) { - usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); - continue; - } -#ifdef ENUM_DEBUG - usbi_dbg("PRO: %s", dev_id_path); -#endif - - // The SPDRP_ADDRESS for USB devices is the device port number on the hub - port_nr = 0; - if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) { - if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, - ®_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) { - usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s", - dev_id_path, windows_error_str(0)); - continue; - } - } - - // Set API to use or get additional data from generic pass - api = USB_API_UNSUPPORTED; - sub_api = SUB_API_NOTSET; - switch (pass) { - case HCD_PASS: - break; - case GEN_PASS: - // We use the GEN pass to detect driverless devices... - size = sizeof(strbuf); - if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER, - ®_type, (BYTE *)strbuf, size, &size)) { - usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path); - usbi_info(ctx, "libusb will not be able to access it."); - } - // ...and to add the additional device interface GUIDs - key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (key != INVALID_HANDLE_VALUE) { - size = sizeof(guid_string_w); - s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, - (BYTE *)guid_string_w, &size); - pRegCloseKey(key); - if (s == ERROR_SUCCESS) { - if (nb_guids >= MAX_ENUM_GUIDS) { - // If this assert is ever reported, grow a GUID table dynamically - usbi_err(ctx, "program assertion failed: too many GUIDs"); - LOOP_BREAK(LIBUSB_ERROR_OVERFLOW); - } - if_guid = calloc(1, sizeof(GUID)); - if (if_guid == NULL) { - usbi_err(ctx, "could not calloc for if_guid: not enough memory"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - pCLSIDFromString(guid_string_w, if_guid); - guid[nb_guids++] = if_guid; - usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); - } - } - break; - case HID_PASS: - api = USB_API_HID; - break; - default: - // Get the API type (after checking that the driver installation is OK) - if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE, - ®_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) { - usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", - dev_id_path, windows_error_str(0)); - } else if (install_state != 0) { - usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", - dev_id_path, (unsigned int)install_state); - continue; - } - get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api); - break; - } - - // Find parent device (for the passes that need it) - switch (pass) { - case HCD_PASS: - case DEV_PASS: - case HUB_PASS: - break; - default: - // Go through the ancestors until we see a face we recognize - parent_dev = NULL; - for (ancestor = 1; parent_dev == NULL; ancestor++) { - session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor); - if (session_id == 0) - break; - - parent_dev = usbi_get_device_by_session_id(ctx, session_id); - } - - if (parent_dev == NULL) { - usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path); - continue; - } - - parent_priv = _device_priv(parent_dev); - // virtual USB devices are also listed during GEN - don't process these yet - if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { - libusb_unref_device(parent_dev); - continue; - } - - break; - } - - // Create new or match existing device, using the (hashed) device_id as session id - if (pass <= DEV_PASS) { // For subsequent passes, we'll lookup the parent - // These are the passes that create "new" devices - session_id = htab_hash(dev_id_path); - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - if (pass == DEV_PASS) { - // This can occur if the OS only reports a newly plugged device after we started enum - usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)" - " - ignoring", dev_id_path); - continue; - } - - usbi_dbg("allocating new device for session [%lX]", session_id); - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - priv = windows_device_priv_init(dev); - } else { - usbi_dbg("found existing device for session [%lX] (%u.%u)", - session_id, dev->bus_number, dev->device_address); - - priv = _device_priv(dev); - if ((parent_dev != NULL) && (dev->parent_dev != NULL)) { - if (dev->parent_dev != parent_dev) { - // It is possible for the actual parent device to not have existed at the - // time of enumeration, so the currently assigned parent may in fact be a - // grandparent. If the devices differ, we assume the "new" parent device - // is in fact closer to the device. - usbi_dbg("updating parent device [session %lX -> %lX]", - dev->parent_dev->session_data, parent_dev->session_data); - libusb_unref_device(dev->parent_dev); - dev->parent_dev = parent_dev; - } else { - // We hold a reference to parent_dev instance, but this device already - // has a parent_dev reference (only one per child) - libusb_unref_device(parent_dev); - } - } - } - - // Keep track of devices that need unref - unref_list[unref_cur++] = dev; - if (unref_cur >= unref_size) { - unref_size += 64; - new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); - if (new_unref_list == NULL) { - usbi_err(ctx, "could not realloc list for unref - aborting."); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } else { - unref_list = new_unref_list; - } - } - } - - // Setup device - switch (pass) { - case HCD_PASS: - // If the hcd has already been setup, don't do it again - if (priv->path != NULL) - break; - dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected - dev->device_address = 0; - dev->num_configurations = 0; - priv->apib = &usb_api_backend[USB_API_HUB]; - priv->sub_api = SUB_API_NOTSET; - priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs - priv->path = dev_interface_path; - dev_interface_path = NULL; - break; - case HUB_PASS: - case DEV_PASS: - // If the device has already been setup, don't do it again - if (priv->path != NULL) - break; - // Take care of API initialization - priv->path = dev_interface_path; - dev_interface_path = NULL; - priv->apib = &usb_api_backend[api]; - priv->sub_api = sub_api; - switch(api) { - case USB_API_COMPOSITE: - case USB_API_HUB: - break; - case USB_API_HID: - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - priv->hid->nb_interfaces = 0; - break; - default: - // For other devices, the first interface is the same as the device - priv->usb_interface[0].path = _strdup(priv->path); - if (priv->usb_interface[0].path == NULL) - usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path); - // The following is needed if we want API calls to work for both simple - // and composite devices. - for (j = 0; j < USB_MAXINTERFACES; j++) - priv->usb_interface[j].apib = &usb_api_backend[api]; - - break; - } - break; - case GEN_PASS: - r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst); - if (r == LIBUSB_SUCCESS) { - // Append device to the list of discovered devices - discdevs = discovered_devs_append(*_discdevs, dev); - if (!discdevs) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - *_discdevs = discdevs; - } else if (r == LIBUSB_ERROR_NO_DEVICE) { - // This can occur if the device was disconnected but Windows hasn't - // refreshed its enumeration yet - in that case, we ignore the device - r = LIBUSB_SUCCESS; - } - break; - default: // HID_PASS and later - if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { - if (parent_priv->apib->id == USB_API_HID) { - usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); - r = set_hid_interface(ctx, parent_dev, dev_interface_path); - } else { - usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); - r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api); - } - switch (r) { - case LIBUSB_SUCCESS: - dev_interface_path = NULL; - break; - case LIBUSB_ERROR_ACCESS: - // interface has already been set => make sure dev_interface_path is freed then - r = LIBUSB_SUCCESS; - break; - default: - LOOP_BREAK(r); - break; - } - } - libusb_unref_device(parent_dev); - break; - } - } - } - - // Free any additional GUIDs - for (pass = HID_PASS + 1; pass < nb_guids; pass++) - free((void *)guid[pass]); - - // Unref newly allocated devs - for (i = 0; i < unref_cur; i++) - libusb_unref_device(unref_list[i]); - free(unref_list); - - return r; -} - -/* - * exit: libusb backend deinitialization function - */ -static void windows_exit(void) -{ - int i; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - - memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; - - return LIBUSB_SUCCESS; -} - -static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; - - // config index is zero based - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; - - if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index]; - - size = MIN(config_header->wTotalLength, len); - memcpy(buffer, priv->config_descriptor[config_index], size); - *host_endian = 0; - - return (int)size; -} - -static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, - unsigned char **buffer, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - uint8_t index; - - *buffer = NULL; - *host_endian = 0; - - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NOT_FOUND; - - for (index = 0; index < dev->num_configurations; index++) { - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index]; - if (config_header->bConfigurationValue == bConfigurationValue) { - *buffer = priv->config_descriptor[index]; - return (int)config_header->wTotalLength; - } - } - - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * return the cached copy of the active config descriptor - */ -static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - unsigned char *config_desc; - int r; - - if (priv->active_config == 0) - return LIBUSB_ERROR_NOT_FOUND; - - r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian); - if (r < 0) - return r; - - len = MIN((size_t)r, len); - memcpy(buffer, config_desc, len); - return (int)len; -} - -static int windows_open(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - if (priv->apib == NULL) { - usbi_err(ctx, "program assertion failed - device is not initialized"); - return LIBUSB_ERROR_NO_DEVICE; - } - - return priv->apib->open(SUB_API_NOTSET, dev_handle); -} - -static void windows_close(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - priv->apib->close(SUB_API_NOTSET, dev_handle); -} - -static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - if (priv->active_config == 0) { - *config = 0; - return LIBUSB_ERROR_NOT_FOUND; - } - - *config = priv->active_config; - return LIBUSB_SUCCESS; -} - -/* - * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver - * does not currently expose a service that allows higher-level drivers to set - * the configuration." - */ -static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_SUCCESS; - - if (config >= USB_MAXCONFIG) - return LIBUSB_ERROR_INVALID_PARAM; - - r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | - LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, - LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, - 0, NULL, 0, 1000); - - if (r == LIBUSB_SUCCESS) - priv->active_config = (uint8_t)config; - - return r; -} - -static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, 0); - - return r; -} - -static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, altsetting); - - return r; -} - -static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); -} - -static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); -} - -static int windows_reset_device(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); -} - -// The 3 functions below are unlikely to ever get supported on Windows -static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void windows_destroy_device(struct libusb_device *dev) -{ - windows_device_priv_release(dev); -} - -void windows_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_free_fd(&transfer_priv->pollable_fd); - safe_free(transfer_priv->hid_buffer); - // When auto claim is in use, attempt to release the auto-claimed interface - auto_release(itransfer); -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; -} - -static int submit_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - - return LIBUSB_SUCCESS; -} - -static int windows_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int windows_abort_control(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->apib->abort_control(SUB_API_NOTSET, itransfer); -} - -static int windows_abort_transfers(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); -} - -static int windows_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return windows_abort_control(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return windows_abort_transfers(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); -} - -struct winfd *windows_get_fd(struct usbi_transfer *transfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer); - return &transfer_priv->pollable_fd; -} - -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) -{ - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { - *io_result = NO_ERROR; - *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; - } else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { - // Regular async overlapped - *io_result = NO_ERROR; - } else { - *io_result = GetLastError(); - } -} - -// NB: MSVC6 does not support named initializers. -const struct usbi_os_backend windows_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - windows_init, - windows_exit, - - windows_get_device_list, - NULL, /* hotplug_poll */ - windows_open, - windows_close, - - windows_get_device_descriptor, - windows_get_active_config_descriptor, - windows_get_config_descriptor, - windows_get_config_descriptor_by_value, - - windows_get_configuration, - windows_set_configuration, - windows_claim_interface, - windows_release_interface, - - windows_set_interface_altsetting, - windows_clear_halt, - windows_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc */ - NULL, /* dev_mem_free */ - - windows_kernel_driver_active, - windows_detach_kernel_driver, - windows_attach_kernel_driver, - - windows_destroy_device, - - windows_submit_transfer, - windows_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - windows_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct windows_device_priv), - sizeof(struct windows_device_handle_priv), - sizeof(struct windows_transfer_priv), -}; - - -/* - * USB API backends - */ -static int unsupported_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} - -static int unsupported_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - -static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(open); -} - -static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - usbi_dbg("unsupported API call for 'close'"); -} - -static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(configure_endpoints); -} - -static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(claim_interface); -} - -static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - PRINT_UNSUPPORTED_API(set_interface_altsetting); -} - -static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(release_interface); -} - -static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - PRINT_UNSUPPORTED_API(clear_halt); -} - -static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(reset_device); -} - -static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_bulk_transfer); -} - -static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_iso_transfer); -} - -static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_control_transfer); -} - -static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_control); -} - -static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_transfers); -} - -static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - PRINT_UNSUPPORTED_API(copy_transfer_data); -} - -static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_SUCCESS; -} - -// These names must be uppercase -static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"}; -static const char *composite_driver_names[] = {"USBCCGP"}; -static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES; -static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; -const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { - { - USB_API_UNSUPPORTED, - "Unsupported API", - NULL, - 0, - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, - }, - { - USB_API_HUB, - "HUB API", - hub_driver_names, - ARRAYSIZE(hub_driver_names), - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, - }, - { - USB_API_COMPOSITE, - "Composite API", - composite_driver_names, - ARRAYSIZE(composite_driver_names), - composite_init, - composite_exit, - composite_open, - composite_close, - common_configure_endpoints, - composite_claim_interface, - composite_set_interface_altsetting, - composite_release_interface, - composite_clear_halt, - composite_reset_device, - composite_submit_bulk_transfer, - composite_submit_iso_transfer, - composite_submit_control_transfer, - composite_abort_control, - composite_abort_transfers, - composite_copy_transfer_data, - }, - { - USB_API_WINUSBX, - "WinUSB-like APIs", - winusbx_driver_names, - ARRAYSIZE(winusbx_driver_names), - winusbx_init, - winusbx_exit, - winusbx_open, - winusbx_close, - winusbx_configure_endpoints, - winusbx_claim_interface, - winusbx_set_interface_altsetting, - winusbx_release_interface, - winusbx_clear_halt, - winusbx_reset_device, - winusbx_submit_bulk_transfer, - unsupported_submit_iso_transfer, - winusbx_submit_control_transfer, - winusbx_abort_control, - winusbx_abort_transfers, - winusbx_copy_transfer_data, - }, - { - USB_API_HID, - "HID API", - hid_driver_names, - ARRAYSIZE(hid_driver_names), - hid_init, - hid_exit, - hid_open, - hid_close, - common_configure_endpoints, - hid_claim_interface, - hid_set_interface_altsetting, - hid_release_interface, - hid_clear_halt, - hid_reset_device, - hid_submit_bulk_transfer, - unsupported_submit_iso_transfer, - hid_submit_control_transfer, - hid_abort_transfers, - hid_abort_transfers, - hid_copy_transfer_data, - }, -}; - - -/* - * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions - */ -#define WinUSBX_Set(fn) \ - do { \ - if (native_winusb) \ - WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ - else \ - pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ - } while (0) - -static int winusbx_init(int sub_api, struct libusb_context *ctx) -{ - HMODULE h; - bool native_winusb; - int i; - KLIB_VERSION LibK_Version; - LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; - LibK_GetVersion_t pLibK_GetVersion; - - h = LoadLibraryA("libusbK"); - - if (h == NULL) { - usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); - h = LoadLibraryA("WinUSB"); - - if (h == NULL) { - usbi_warn(ctx, "WinUSB DLL is not available either, " - "you will not be able to access devices outside of enumeration"); - return LIBUSB_ERROR_NOT_FOUND; - } - } else { - usbi_dbg("using libusbK DLL for universal access"); - pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); - if (pLibK_GetVersion != NULL) { - pLibK_GetVersion(&LibK_Version); - usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, - LibK_Version.Micro, LibK_Version.Nano); - } - pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); - if (pLibK_GetProcAddress == NULL) { - usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); - FreeLibrary(h); - return LIBUSB_ERROR_NOT_FOUND; - } - } - - native_winusb = (pLibK_GetProcAddress == NULL); - for (i = SUB_API_LIBUSBK; i < SUB_API_MAX; i++) { - WinUSBX_Set(AbortPipe); - WinUSBX_Set(ControlTransfer); - WinUSBX_Set(FlushPipe); - WinUSBX_Set(Free); - WinUSBX_Set(GetAssociatedInterface); - WinUSBX_Set(GetCurrentAlternateSetting); - WinUSBX_Set(GetDescriptor); - WinUSBX_Set(GetOverlappedResult); - WinUSBX_Set(GetPipePolicy); - WinUSBX_Set(GetPowerPolicy); - WinUSBX_Set(Initialize); - WinUSBX_Set(QueryDeviceInformation); - WinUSBX_Set(QueryInterfaceSettings); - WinUSBX_Set(QueryPipe); - WinUSBX_Set(ReadPipe); - WinUSBX_Set(ResetPipe); - WinUSBX_Set(SetCurrentAlternateSetting); - WinUSBX_Set(SetPipePolicy); - WinUSBX_Set(SetPowerPolicy); - WinUSBX_Set(WritePipe); - if (!native_winusb) - WinUSBX_Set(ResetDevice); - - if (WinUSBX[i].Initialize != NULL) { - WinUSBX[i].initialized = true; - usbi_dbg("initalized sub API %s", sub_api_name[i]); - } else { - usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]); - WinUSBX[i].initialized = false; - } - } - - WinUSBX_handle = h; - return LIBUSB_SUCCESS; -} - -static int winusbx_exit(int sub_api) -{ - if (WinUSBX_handle != NULL) { - FreeLibrary(WinUSBX_handle); - WinUSBX_handle = NULL; - - /* Reset the WinUSBX API structures */ - memset(&WinUSBX, 0, sizeof(WinUSBX)); - } - - return LIBUSB_SUCCESS; -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - - HANDLE file_handle; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // WinUSB requires a separate handle for each interface - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { - file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); - switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - handle_priv->interface_handle[i].dev_handle = file_handle; - } - } - - return LIBUSB_SUCCESS; -} - -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE handle; - int i; - - if (sub_api == SUB_API_NOTSET) - sub_api = priv->sub_api; - - if (!WinUSBX[sub_api].initialized) - return; - - if (priv->apib->id == USB_API_COMPOSITE) { - // If this is a composite device, just free and close all WinUSB-like - // interfaces directly (each is independent and not associated with another) - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[i].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } - } - } else { - // If this is a WinUSB device, free all interfaces above interface 0, - // then free and close interface 0 last - for (i = 1; i < USB_MAXINTERFACES; i++) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - } - handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[0].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } -} - -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; - UCHAR policy; - ULONG timeout = 0; - uint8_t endpoint_address; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // With handle and enpoints set (in parent), we can setup the default pipe properties - // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx - for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { - endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) - usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); - - if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) - continue; // Other policies don't apply to control endpoint or libusb0 - - policy = false; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); - - policy = true; - /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: - https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - HDEVINFO dev_info = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA dev_info_data; - char *dev_path_no_guid = NULL; - char filter_path[] = "\\\\.\\libusb0-0000"; - bool found_filter = false; - HANDLE file_handle, winusb_handle; - DWORD err; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // If the device is composite, but using the default Windows composite parent driver (usbccgp) - // or if it's the first WinUSB-like interface, we get a handle through Initialize(). - if ((is_using_usbccgp) || (iface == 0)) { - // composite device (independent interfaces) or interface 0 - file_handle = handle_priv->interface_handle[iface].dev_handle; - if (!HANDLE_VALID(file_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - err = GetLastError(); - switch(err) { - case ERROR_BAD_COMMAND: - // The device was disconnected - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - default: - // it may be that we're using the libusb0 filter driver. - // TODO: can we move this whole business into the K/0 DLL? - for (i = 0; ; i++) { - safe_free(dev_interface_details); - safe_free(dev_path_no_guid); - - dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); - if ((found_filter) || (dev_interface_details == NULL)) - break; - - // ignore GUID part - dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); - if (dev_path_no_guid == NULL) - continue; - - if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { - file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle != INVALID_HANDLE_VALUE) { - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - // Replace the existing file handle with the working one - CloseHandle(handle_priv->interface_handle[iface].dev_handle); - handle_priv->interface_handle[iface].dev_handle = file_handle; - found_filter = true; - } else { - usbi_err(ctx, "could not initialize filter driver for %s", filter_path); - CloseHandle(file_handle); - } - } else { - usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); - } - } - } - free(dev_interface_details); - if (!found_filter) { - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); - return LIBUSB_ERROR_ACCESS; - } - } - } - handle_priv->interface_handle[iface].api_handle = winusb_handle; - } else { - // For all other interfaces, use GetAssociatedInterface() - winusb_handle = handle_priv->interface_handle[0].api_handle; - // It is a requirement for multiple interface devices on Windows that, to you - // must first claim the first interface before you claim the others - if (!HANDLE_VALID(winusb_handle)) { - file_handle = handle_priv->interface_handle[0].dev_handle; - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[0].api_handle = winusb_handle; - usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface); - } else { - usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), - &handle_priv->interface_handle[iface].api_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - switch(GetLastError()) { - case ERROR_NO_MORE_ITEMS: // invalid iface - return LIBUSB_ERROR_NOT_FOUND; - case ERROR_BAD_COMMAND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ALREADY_EXISTS: // already claimed - return LIBUSB_ERROR_BUSY; - default: - usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - } - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - WinUSBX[sub_api].Free(winusb_handle); - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -/* - * Return the first valid interface (of the same API type), for control transfers - */ -static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int i; - - if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { - usbi_dbg("unsupported API ID"); - return -1; - } - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) - && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) - && (priv->usb_interface[i].apib->id == api_id)) - return i; - } - - return -1; -} - -/* - * Lookup interface by endpoint address. -1 if not found - */ -static int interface_by_endpoint(struct windows_device_priv *priv, - struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address) -{ - int i, j; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) - continue; - if (priv->usb_interface[i].endpoint == NULL) - continue; - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - if (priv->usb_interface[i].endpoint[j] == endpoint_address) - return i; - } - } - - return -1; -} - -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - ULONG size; - HANDLE winusb_handle; - int current_interface; - struct winfd wfd; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - transfer_priv->pollable_fd = INVALID_WINFD; - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - // Windows places upper limits on the control transfer size - // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx - if (size > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); - if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("will use interface %d", current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - // Sending of set configuration control requests from WinUSB creates issues - if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD) - && (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) { - if (setup->value != priv->active_config) { - usbi_warn(ctx, "cannot set configuration other than the default one"); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_INVALID_PARAM; - } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = 0; - } else { - if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)size; - } - } - - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - if (altsetting > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) { - usbi_err(ctx, "interface must be claimed first"); - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) { - usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - bool ret; - int current_interface; - struct winfd wfd; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - transfer_priv->pollable_fd = INVALID_WINFD; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - if (IS_XFERIN(transfer)) { - usbi_dbg("reading %d bytes", transfer->length); - ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); - } else { - usbi_dbg("writing %d bytes", transfer->length); - ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)transfer->length; - } - - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed - * through testing as well): - * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel - * the control transfer using CancelIo" - */ -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - // Cancelling of the I/O is done in the parent - return LIBUSB_SUCCESS; -} - -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = transfer_priv->interface_number; - if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { - usbi_err(ctx, "program assertion failed: invalid interface_number"); - return LIBUSB_ERROR_NOT_FOUND; - } - usbi_dbg("will use interface %d", current_interface); - - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper - * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx): - * "WinUSB does not support host-initiated reset port and cycle port operations" and - * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the - * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is - * cycle the pipes (and even then, the control pipe can not be reset using WinUSB) - */ -// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?) -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct winfd wfd; - HANDLE winusb_handle; - int i, j; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // Reset any available pipe (except control) - for (i = 0; i < USB_MAXINTERFACES; i++) { - winusb_handle = handle_priv->interface_handle[i].api_handle; - for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) { - // Cancel any pollable I/O - usbi_remove_pollfd(ctx, wfd.fd); - usbi_free_fd(&wfd); - wfd = handle_to_winfd(winusb_handle); - } - - if (HANDLE_VALID(winusb_handle)) { - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - // FlushPipe seems to fail on OUT pipes - if (IS_EPIN(priv->usb_interface[i].endpoint[j]) - && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) - usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } - } - } - - // libusbK & libusb0 have the ability to issue an actual device reset - if (WinUSBX[sub_api].ResetDevice != NULL) { - winusb_handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(winusb_handle)) - WinUSBX[sub_api].ResetDevice(winusb_handle); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; -} - -/* - * Internal HID Support functions (from libusb-win32) - * Note that functions that complete data transfer synchronously must return - * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS - */ -static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size); -static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size); - -static int _hid_wcslen(WCHAR *str) -{ - int i = 0; - - while (str[i] && (str[i] != 0x409)) - i++; - - return i; -} - -static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - struct libusb_device_descriptor d; - - d.bLength = LIBUSB_DT_DEVICE_SIZE; - d.bDescriptorType = LIBUSB_DT_DEVICE; - d.bcdUSB = 0x0200; /* 2.00 */ - d.bDeviceClass = 0; - d.bDeviceSubClass = 0; - d.bDeviceProtocol = 0; - d.bMaxPacketSize0 = 64; /* fix this! */ - d.idVendor = (uint16_t)dev->vid; - d.idProduct = (uint16_t)dev->pid; - d.bcdDevice = 0x0100; - d.iManufacturer = dev->string_index[0]; - d.iProduct = dev->string_index[1]; - d.iSerialNumber = dev->string_index[2]; - d.bNumConfigurations = 1; - - if (*size > LIBUSB_DT_DEVICE_SIZE) - *size = LIBUSB_DT_DEVICE_SIZE; - memcpy(data, &d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - char num_endpoints = 0; - size_t config_total_len = 0; - char tmp[HID_MAX_CONFIG_DESC_SIZE]; - struct libusb_config_descriptor *cd; - struct libusb_interface_descriptor *id; - struct libusb_hid_descriptor *hd; - struct libusb_endpoint_descriptor *ed; - size_t tmp_size; - - if (dev->input_report_size) - num_endpoints++; - if (dev->output_report_size) - num_endpoints++; - - config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE - + LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE; - - cd = (struct libusb_config_descriptor *)tmp; - id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE); - hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE - + LIBUSB_DT_INTERFACE_SIZE); - ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE - + LIBUSB_DT_INTERFACE_SIZE - + LIBUSB_DT_HID_SIZE); - - cd->bLength = LIBUSB_DT_CONFIG_SIZE; - cd->bDescriptorType = LIBUSB_DT_CONFIG; - cd->wTotalLength = (uint16_t)config_total_len; - cd->bNumInterfaces = 1; - cd->bConfigurationValue = 1; - cd->iConfiguration = 0; - cd->bmAttributes = 1 << 7; /* bus powered */ - cd->MaxPower = 50; - - id->bLength = LIBUSB_DT_INTERFACE_SIZE; - id->bDescriptorType = LIBUSB_DT_INTERFACE; - id->bInterfaceNumber = 0; - id->bAlternateSetting = 0; - id->bNumEndpoints = num_endpoints; - id->bInterfaceClass = 3; - id->bInterfaceSubClass = 0; - id->bInterfaceProtocol = 0; - id->iInterface = 0; - - tmp_size = LIBUSB_DT_HID_SIZE; - _hid_get_hid_descriptor(dev, hd, &tmp_size); - - if (dev->input_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_IN_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->input_report_size - 1; - ed->bInterval = 10; - ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE); - } - - if (dev->output_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_OUT_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->output_report_size - 1; - ed->bInterval = 10; - } - - if (*size > config_total_len) - *size = config_total_len; - memcpy(data, tmp, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index, - void *data, size_t *size) -{ - void *tmp = NULL; - size_t tmp_size = 0; - int i; - - /* language ID, EN-US */ - char string_langid[] = {0x09, 0x04}; - - if ((*size < 2) || (*size > 255)) - return LIBUSB_ERROR_OVERFLOW; - - if (_index == 0) { - tmp = string_langid; - tmp_size = sizeof(string_langid) + 2; - } else { - for (i = 0; i < 3; i++) { - if (_index == (dev->string_index[i])) { - tmp = dev->string[i]; - tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR); - break; - } - } - - if (i == 3) // not found - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (!tmp_size) - return LIBUSB_ERROR_INVALID_PARAM; - - if (tmp_size < *size) - *size = tmp_size; - - // 2 byte header - ((uint8_t *)data)[0] = (uint8_t)*size; - ((uint8_t *)data)[1] = LIBUSB_DT_STRING; - memcpy((uint8_t *)data + 2, tmp, *size - 2); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - struct libusb_hid_descriptor d; - uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE]; - size_t report_len = MAX_HID_DESCRIPTOR_SIZE; - - _hid_get_report_descriptor(dev, tmp, &report_len); - - d.bLength = LIBUSB_DT_HID_SIZE; - d.bDescriptorType = LIBUSB_DT_HID; - d.bcdHID = 0x0110; /* 1.10 */ - d.bCountryCode = 0; - d.bNumDescriptors = 1; - d.bClassDescriptorType = LIBUSB_DT_REPORT; - d.wClassDescriptorLength = (uint16_t)report_len; - - if (*size > LIBUSB_DT_HID_SIZE) - *size = LIBUSB_DT_HID_SIZE; - memcpy(data, &d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - uint8_t d[MAX_HID_DESCRIPTOR_SIZE]; - size_t i = 0; - - /* usage page (0xFFA0 == vendor defined) */ - d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF; - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* start collection (application) */ - d[i++] = 0xA1; d[i++] = 0x01; - /* input report */ - if (dev->input_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1; - /* input (data, variable, absolute) */ - d[i++] = 0x81; d[i++] = 0x00; - } - /* output report */ - if (dev->output_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x02; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1; - /* output (data, variable, absolute) */ - d[i++] = 0x91; d[i++] = 0x00; - } - /* feature report */ - if (dev->feature_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x03; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1; - /* feature (data, variable, absolute) */ - d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01; - } - - /* end collection */ - d[i++] = 0xC0; - - if (*size > i) - *size = i; - memcpy(data, d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient, - int type, int _index, void *data, size_t *size) -{ - switch(type) { - case LIBUSB_DT_DEVICE: - usbi_dbg("LIBUSB_DT_DEVICE"); - return _hid_get_device_descriptor(dev, data, size); - case LIBUSB_DT_CONFIG: - usbi_dbg("LIBUSB_DT_CONFIG"); - if (!_index) - return _hid_get_config_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_STRING: - usbi_dbg("LIBUSB_DT_STRING"); - return _hid_get_string_descriptor(dev, _index, data, size); - case LIBUSB_DT_HID: - usbi_dbg("LIBUSB_DT_HID"); - if (!_index) - return _hid_get_hid_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_REPORT: - usbi_dbg("LIBUSB_DT_REPORT"); - if (!_index) - return _hid_get_report_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_PHYSICAL: - usbi_dbg("LIBUSB_DT_PHYSICAL"); - if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size)) - return LIBUSB_COMPLETED; - return LIBUSB_ERROR_OTHER; - } - - usbi_dbg("unsupported"); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) -{ - uint8_t *buf; - DWORD ioctl_code, read_size, expected_size = (DWORD)*size; - int r = LIBUSB_SUCCESS; - - if (tp->hid_buffer != NULL) - usbi_dbg("program assertion failed: hid_buffer is not NULL"); - - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { - usbi_dbg("invalid size (%u)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - switch (report_type) { - case HID_REPORT_TYPE_INPUT: - ioctl_code = IOCTL_HID_GET_INPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_GET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - // Add a trailing byte to detect overflows - buf = calloc(1, expected_size + 1); - if (buf == NULL) - return LIBUSB_ERROR_NO_MEM; - - buf[0] = (uint8_t)id; // Must be set always - usbi_dbg("report ID: 0x%02X", buf[0]); - - tp->hid_expected_size = expected_size; - read_size = expected_size; - - // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1, - buf, expected_size + 1, &read_size, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0)); - free(buf); - return LIBUSB_ERROR_IO; - } - // Asynchronous wait - tp->hid_buffer = buf; - tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously => copy and discard extra buffer - if (read_size == 0) { - usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read"); - *size = 0; - } else { - if (buf[0] != id) - usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - - if ((size_t)read_size > expected_size) { - r = LIBUSB_ERROR_OVERFLOW; - usbi_dbg("OVERFLOW!"); - } else { - r = LIBUSB_COMPLETED; - } - - *size = MIN((size_t)read_size, *size); - if (id == 0) - memcpy(data, buf + 1, *size); // Discard report ID - else - memcpy(data, buf, *size); - } - - free(buf); - return r; -} - -static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) -{ - uint8_t *buf = NULL; - DWORD ioctl_code, write_size = (DWORD)*size; - - if (tp->hid_buffer != NULL) - usbi_dbg("program assertion failed: hid_buffer is not NULL"); - - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { - usbi_dbg("invalid size (%u)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - switch (report_type) { - case HID_REPORT_TYPE_OUTPUT: - ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_SET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_dbg("report ID: 0x%02X", id); - // When report IDs are not used (i.e. when id == 0), we must add - // a null report ID. Otherwise, we just use original data buffer - if (id == 0) - write_size++; - - buf = malloc(write_size); - if (buf == NULL) - return LIBUSB_ERROR_NO_MEM; - - if (id == 0) { - buf[0] = 0; - memcpy(buf + 1, data, *size); - } else { - // This seems like a waste, but if we don't duplicate the - // data, we'll get issues when freeing hid_buffer - memcpy(buf, data, *size); - if (buf[0] != id) - usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - } - - // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size, - buf, write_size, &write_size, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0)); - free(buf); - return LIBUSB_ERROR_IO; - } - tp->hid_buffer = buf; - tp->hid_dest = NULL; - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously - *size = write_size; - if (write_size == 0) - usbi_dbg("program assertion failed - write completed synchronously, but no data was written"); - - free(buf); - return LIBUSB_COMPLETED; -} - -static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type, - int request, int value, int _index, void *data, struct windows_transfer_priv *tp, - size_t *size, OVERLAPPED *overlapped) -{ - int report_type = (value >> 8) & 0xFF; - int report_id = value & 0xFF; - - if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE) - && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE)) - return LIBUSB_ERROR_INVALID_PARAM; - - if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT) - return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT) - return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - return LIBUSB_ERROR_INVALID_PARAM; -} - - -/* - * HID API functions - */ -static int hid_init(int sub_api, struct libusb_context *ctx) -{ - DLL_GET_HANDLE(hid); - DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE); - DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE); - DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE); - DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE); - DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE); - DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE); - DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE); - DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE); - - api_hid_available = true; - return LIBUSB_SUCCESS; -} - -static int hid_exit(int sub_api) -{ - DLL_FREE_HANDLE(hid); - - return LIBUSB_SUCCESS; -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HIDD_ATTRIBUTES hid_attributes; - PHIDP_PREPARSED_DATA preparsed_data = NULL; - HIDP_CAPS capabilities; - HIDP_VALUE_CAPS *value_caps; - HANDLE hid_handle = INVALID_HANDLE_VALUE; - int i, j; - // report IDs handling - ULONG size[3]; - int nb_ids[2]; // zero and nonzero report IDs -#if defined(ENABLE_LOGGING) - const char *type[3] = {"input", "output", "feature"}; -#endif - - CHECK_HID_AVAILABLE; - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed - private HID structure is unitialized"); - return LIBUSB_ERROR_NOT_FOUND; - } - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_HID)) { - hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - /* - * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID? - * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system - * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not - * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and - * HidD_GetFeature (if the device supports Feature reports)." - */ - if (hid_handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without"); - hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (hid_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0)); - switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - priv->usb_interface[i].restricted_functionality = true; - } - handle_priv->interface_handle[i].api_handle = hid_handle; - } - } - - hid_attributes.Size = sizeof(hid_attributes); - do { - if (!HidD_GetAttributes(hid_handle, &hid_attributes)) { - usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)"); - break; - } - - priv->hid->vid = hid_attributes.VendorID; - priv->hid->pid = hid_attributes.ProductID; - - // Set the maximum available input buffer size - for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2); - usbi_dbg("set maximum input buffer size to %d", i / 2); - - // Get the maximum input and output report size - if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) { - usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)"); - break; - } - if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) { - usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)"); - break; - } - - // Find out if interrupt will need report IDs - size[0] = capabilities.NumberInputValueCaps; - size[1] = capabilities.NumberOutputValueCaps; - size[2] = capabilities.NumberFeatureValueCaps; - for (j = HidP_Input; j <= HidP_Feature; j++) { - usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]); - priv->hid->uses_report_ids[j] = false; - if (size[j] > 0) { - value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS)); - if ((value_caps != NULL) - && (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS) - && (size[j] >= 1)) { - nb_ids[0] = 0; - nb_ids[1] = 0; - for (i = 0; i < (int)size[j]; i++) { - usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID); - if (value_caps[i].ReportID != 0) - nb_ids[1]++; - else - nb_ids[0]++; - } - if (nb_ids[1] != 0) { - if (nb_ids[0] != 0) - usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s", - type[j]); - priv->hid->uses_report_ids[j] = true; - } - } else { - usbi_warn(ctx, " could not process %s report IDs", type[j]); - } - free(value_caps); - } - } - - // Set the report sizes - priv->hid->input_report_size = capabilities.InputReportByteLength; - priv->hid->output_report_size = capabilities.OutputReportByteLength; - priv->hid->feature_report_size = capabilities.FeatureReportByteLength; - - // Fetch string descriptors - priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer; - if (priv->hid->string_index[0] != 0) - HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0])); - else - priv->hid->string[0][0] = 0; - - priv->hid->string_index[1] = priv->dev_descriptor.iProduct; - if (priv->hid->string_index[1] != 0) - HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1])); - else - priv->hid->string[1][0] = 0; - - priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber; - if (priv->hid->string_index[2] != 0) - HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2])); - else - priv->hid->string[2][0] = 0; - } while(0); - - if (preparsed_data) - HidD_FreePreparsedData(preparsed_data); - - return LIBUSB_SUCCESS; -} - -static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HANDLE file_handle; - int i; - - if (!api_hid_available) - return; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].apib->id == USB_API_HID) { - file_handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(file_handle)) - CloseHandle(file_handle); - } - } -} - -static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - // NB: Disconnection detection is not possible in this function - if (priv->usb_interface[iface].path == NULL) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - // We use dev_handle as a flag for interface claimed - if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED) - return LIBUSB_ERROR_BUSY; // already claimed - - - handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED; - - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - if (priv->usb_interface[iface].path == NULL) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - if (altsetting > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - if (altsetting != 0) { - usbi_err(ctx, "set interface altsetting not supported for altsetting >0"); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - return LIBUSB_SUCCESS; -} - -static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - HANDLE hid_handle; - struct winfd wfd; - int current_interface, config; - size_t size; - int r = LIBUSB_ERROR_INVALID_PARAM; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - safe_free(transfer_priv->hid_buffer); - transfer_priv->hid_dest = NULL; - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - if (size > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID); - if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("will use interface %d", current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - // Always use the handle returned from usbi_create_fd (wfd.handle) - wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL); - if (wfd.fd < 0) - return LIBUSB_ERROR_NOT_FOUND; - - switch(LIBUSB_REQ_TYPE(setup->request_type)) { - case LIBUSB_REQUEST_TYPE_STANDARD: - switch(setup->request) { - case LIBUSB_REQUEST_GET_DESCRIPTOR: - r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type), - (setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size); - break; - case LIBUSB_REQUEST_GET_CONFIGURATION: - r = windows_get_configuration(transfer->dev_handle, &config); - if (r == LIBUSB_SUCCESS) { - size = 1; - ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config; - r = LIBUSB_COMPLETED; - } - break; - case LIBUSB_REQUEST_SET_CONFIGURATION: - if (setup->value == priv->active_config) { - r = LIBUSB_COMPLETED; - } else { - usbi_warn(ctx, "cannot set configuration other than the default one"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - } - break; - case LIBUSB_REQUEST_GET_INTERFACE: - size = 1; - ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0; - r = LIBUSB_COMPLETED; - break; - case LIBUSB_REQUEST_SET_INTERFACE: - r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value); - if (r == LIBUSB_SUCCESS) - r = LIBUSB_COMPLETED; - break; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - break; - case LIBUSB_REQUEST_TYPE_CLASS: - r = _hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value, - setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv, - &size, wfd.overlapped); - break; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (r == LIBUSB_COMPLETED) { - // Force request to be completed synchronously. Transferred size has been set by previous call - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - // http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx - // set InternalHigh to the number of bytes transferred - wfd.overlapped->InternalHigh = (DWORD)size; - r = LIBUSB_SUCCESS; - } - - if (r == LIBUSB_SUCCESS) { - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - } else { - usbi_free_fd(&wfd); - } - - return r; -} - -static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct winfd wfd; - HANDLE hid_handle; - bool direction_in, ret; - int current_interface, length; - DWORD size; - int r = LIBUSB_SUCCESS; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - transfer_priv->hid_dest = NULL; - safe_free(transfer_priv->hid_buffer); - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - - wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - // If report IDs are not in use, an extra prefix byte must be added - if (((direction_in) && (!priv->hid->uses_report_ids[0])) - || ((!direction_in) && (!priv->hid->uses_report_ids[1]))) - length = transfer->length + 1; - else - length = transfer->length; - - // Add a trailing byte to detect overflows on input - transfer_priv->hid_buffer = calloc(1, length + 1); - if (transfer_priv->hid_buffer == NULL) - return LIBUSB_ERROR_NO_MEM; - - transfer_priv->hid_expected_size = length; - - if (direction_in) { - transfer_priv->hid_dest = transfer->buffer; - usbi_dbg("reading %d bytes (report ID: 0x00)", length); - ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped); - } else { - if (!priv->hid->uses_report_ids[1]) - memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length); - else - // We could actually do without the calloc and memcpy in this case - memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length); - - usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]); - ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - safe_free(transfer_priv->hid_buffer); - return LIBUSB_ERROR_IO; - } - } else { - // Only write operations that completed synchronously need to free up - // hid_buffer. For reads, copy_transfer_data() handles that process. - if (!direction_in) - safe_free(transfer_priv->hid_buffer); - - if (size == 0) { - usbi_err(ctx, "program assertion failed - no data was transferred"); - size = 1; - } - if (size > (size_t)length) { - usbi_err(ctx, "OVERFLOW!"); - r = LIBUSB_ERROR_OVERFLOW; - } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = size; - } - - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return r; -} - -static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = transfer_priv->interface_number; - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - CancelIo(hid_handle); - - return LIBUSB_SUCCESS; -} - -static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - // Flushing the queues on all interfaces is the best we can achieve - for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - if (HANDLE_VALID(hid_handle)) - HidD_FlushQueue(hid_handle); - } - - return LIBUSB_SUCCESS; -} - -static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - - // No endpoint selection with Microsoft's implementation, so we try to flush the - // whole interface. Should be OK for most case scenarios - if (!HidD_FlushQueue(hid_handle)) { - usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0)); - // Device was probably disconnected - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -// This extra function is only needed for HID -static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - int r = LIBUSB_TRANSFER_COMPLETED; - uint32_t corrected_size = io_size; - - if (transfer_priv->hid_buffer != NULL) { - // If we have a valid hid_buffer, it means the transfer was async - if (transfer_priv->hid_dest != NULL) { // Data readout - if (corrected_size > 0) { - // First, check for overflow - if (corrected_size > transfer_priv->hid_expected_size) { - usbi_err(ctx, "OVERFLOW!"); - corrected_size = (uint32_t)transfer_priv->hid_expected_size; - r = LIBUSB_TRANSFER_OVERFLOW; - } - - if (transfer_priv->hid_buffer[0] == 0) { - // Discard the 1 byte report ID prefix - corrected_size--; - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size); - } else { - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size); - } - } - transfer_priv->hid_dest = NULL; - } - // For write, we just need to free the hid buffer - safe_free(transfer_priv->hid_buffer); - } - - itransfer->transferred += corrected_size; - return r; -} - - -/* - * Composite API functions - */ -static int composite_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} - -static int composite_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_ERROR_NOT_FOUND; - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) - available[priv->usb_interface[i].sub_api] = true; - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle); - if (r != LIBUSB_SUCCESS) - return r; - } - } - - if (available[SUB_API_MAX]) // HID driver - r = hid_open(SUB_API_NOTSET, dev_handle); - - return r; -} - -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) - available[priv->usb_interface[i].sub_api] = true; - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) - usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); - } - - if (available[SUB_API_MAX]) // HID driver - hid_close(SUB_API_NOTSET, dev_handle); -} - -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); -} - -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - int iface, pass, r; - - // Interface shouldn't matter for control, but it does in practice, with Windows' - // restrictions with regards to accessing HID keyboards and mice. Try to target - // a specific interface first, if possible. - switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) { - case LIBUSB_RECIPIENT_INTERFACE: - iface = setup->index & 0xFF; - break; - case LIBUSB_RECIPIENT_ENDPOINT: - r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); - if (r == LIBUSB_SUCCESS) { - iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF)); - libusb_free_config_descriptor(conf_desc); - break; - } - // Fall through if not able to determine interface - default: - iface = -1; - break; - } - - // Try and target a specific interface if the control setup indicates such - if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { - usbi_dbg("attempting control transfer targeted to interface %d", iface); - if (priv->usb_interface[iface].path != NULL) { - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - if (r == LIBUSB_SUCCESS) - return r; - } - } - - // Either not targeted to a specific interface or no luck in doing so. - // Try a 2 pass approach with all interfaces. - for (pass = 0; pass < 2; pass++) { - for (iface = 0; iface < USB_MAXINTERFACES; iface++) { - if (priv->usb_interface[iface].path != NULL) { - if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { - usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); - continue; - } - usbi_dbg("using interface %d", iface); - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - // If not supported on this API, it may be supported on another, so don't give up yet!! - if (r == LIBUSB_ERROR_NOT_SUPPORTED) - continue; - return r; - } - } - } - - usbi_err(ctx, "no libusb supported interfaces to complete request"); - return LIBUSB_ERROR_NOT_FOUND; -} - -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); -} - -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); -} - -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); -} - -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r; - uint8_t i; - bool available[SUB_API_MAX]; - - for (i = 0; i < SUB_API_MAX; i++) - available[i] = false; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) - && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) - available[priv->usb_interface[i].sub_api] = true; - } - - for (i = 0; i < SUB_API_MAX; i++) { - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle); - if (r != LIBUSB_SUCCESS) - return r; - } - } - - return LIBUSB_SUCCESS; -} - -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size); -} - -#endif /* !USE_USBDK */ diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/version_nano.h b/vendor/github.com/karalabe/hid/libusb/libusb/version_nano.h deleted file mode 100644 index 0a5d1c992..000000000 --- a/vendor/github.com/karalabe/hid/libusb/libusb/version_nano.h +++ /dev/null @@ -1 +0,0 @@ -#define LIBUSB_NANO 11182 diff --git a/vendor/github.com/karalabe/usb/.travis.yml b/vendor/github.com/karalabe/usb/.travis.yml new file mode 100644 index 000000000..de0337b2b --- /dev/null +++ b/vendor/github.com/karalabe/usb/.travis.yml @@ -0,0 +1,49 @@ +language: go + +matrix: + include: + - os: linux + dist: trusty + go: 1.5.x + - os: linux + dist: trusty + go: 1.6.x + - os: linux + dist: trusty + go: 1.7.x + - os: linux + dist: trusty + go: 1.8.x + - os: linux + dist: trusty + go: 1.9.x + - os: linux + dist: xenial + go: 1.9.x + - os: linux + dist: xenial + go: 1.10.x + - os: linux + dist: xenial + go: 1.11.x + - os: linux + dist: xenial + go: 1.12.x + - os: osx + go: 1.12.x + - os: linux + dist: xenial + go: 1.12.x + services: + - docker + env: + - docker + script: + - docker build -f Dockerfile.ubuntu . + - docker build -f Dockerfile.alpine . + +script: + - go install ./... + - go test -v ./... + - CGO_ENABLED=0 go install ./... + - CGO_ENABLED=0 go test -v ./... diff --git a/vendor/github.com/karalabe/usb/AUTHORS b/vendor/github.com/karalabe/usb/AUTHORS new file mode 100644 index 000000000..bae45b3ec --- /dev/null +++ b/vendor/github.com/karalabe/usb/AUTHORS @@ -0,0 +1,7 @@ +Felix Lange +Guillaume Ballet +Jakob Weisblat +Martin Holst Swende +Mateusz Mikołajczyk +Péter Szilágyi +Rosen Penev diff --git a/vendor/github.com/karalabe/usb/Dockerfile.alpine b/vendor/github.com/karalabe/usb/Dockerfile.alpine new file mode 100644 index 000000000..342bdf79a --- /dev/null +++ b/vendor/github.com/karalabe/usb/Dockerfile.alpine @@ -0,0 +1,6 @@ +FROM golang:alpine + +RUN apk add --no-cache git gcc musl-dev linux-headers + +ADD . $GOPATH/src/github.com/karalabe/usb +RUN cd $GOPATH/src/github.com/karalabe/usb && go install diff --git a/vendor/github.com/karalabe/usb/Dockerfile.ubuntu b/vendor/github.com/karalabe/usb/Dockerfile.ubuntu new file mode 100644 index 000000000..b861e497b --- /dev/null +++ b/vendor/github.com/karalabe/usb/Dockerfile.ubuntu @@ -0,0 +1,4 @@ +FROM golang:latest + +ADD . $GOPATH/src/github.com/karalabe/usb +RUN cd $GOPATH/src/github.com/karalabe/usb && go install diff --git a/vendor/github.com/karalabe/usb/LICENSE b/vendor/github.com/karalabe/usb/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/vendor/github.com/karalabe/usb/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/github.com/karalabe/usb/README.md b/vendor/github.com/karalabe/usb/README.md new file mode 100644 index 000000000..b6920f51a --- /dev/null +++ b/vendor/github.com/karalabe/usb/README.md @@ -0,0 +1,47 @@ +[![Travis][travisimg]][travisurl] +[![AppVeyor][appveyorimg]][appveyorurl] +[![GoDoc][docimg]][docurl] + +[travisimg]: https://travis-ci.org/karalabe/usb.svg?branch=master +[travisurl]: https://travis-ci.org/karalabe/usb +[appveyorimg]: https://ci.appveyor.com/api/projects/status/u96eq262bj2itprh/branch/master?svg=true +[appveyorurl]: https://ci.appveyor.com/project/karalabe/usb +[docimg]: https://godoc.org/github.com/karalabe/usb?status.svg +[docurl]: https://godoc.org/github.com/karalabe/usb + +# Yet another USB library for Go + +The `usb` package is a cross platform, fully self-contained library for accessing and communicating with USB devices **either via HID or low level interrupts**. The goal of the library was to create a simple way to find-, attach to- and read/write form USB devices. + +There are multiple already existing USB libraries: + + * The original `gousb` package [created by @kylelemons](https://github.com/kylelemons/gousb) and nowadays [maintained by @google](https://github.com/google/gousb) is a CGO wrapper around `libusb`. It is the most advanced USB library for Go out there. + * Unfortunately, `gousb` requires the `libusb` C library to be installed both during build as well as during runtime on the host operating system. This breaks binary portability and also adds unnecessary hurdles on Windows. + * Furthermore, whilst HID devices are supported by `libusb`, the OS on Macos and Windows explicitly takes over these devices, so only native system calls can be used on recent versions (i.e. you **cannot** use `libusb` for HID). + * There is a fork of `gousb` [created by @karalabe](https://github.com/karalabe/gousb) that statically linked `libusb` during build, but with the lack of HID access, that work was abandoned. + * For HID-only devices, a previous self-contained package was created at [`github.com/karalabe/hid`](https://github.com/karalabe/hid), which worked well for hardware wallet uses cases in [`go-ethereum`](https://github.com/ethereum/go-ethereum). It's a simple package that does it's thing well. + * Unfortunately, `hid` is not capable of talking to generic USB devices. When multiple different devices are needed, eventually some will not support the HID spec (e.g. WebUSB). Pulling in both `hid` and `gousb` will break down due to both depending internally on different versions of `libusb` on Linux. + +This `usb` package is a proper integration of `hidapi` and `libusb` so that communication with HID devices is done via system calls, whereas communication with lower level USB devices is done via interrupts. All this detail is hidden away behind a tiny interface. + +The package supports Linux, macOS, Windows and FreeBSD. Exclude constraints are also specified for Android and iOS to allow smoother vendoring into cross platform projects. + +## Cross-compiling + +Using `go get`, the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration `hid.Enumerate()` to yield no results. + +To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via `CGO_ENABLED=1` and you'll need to install and set a cross compilation enabled C toolkit via `CC=your-cross-gcc`. + +## Acknowledgements + +Although the `usb` package is an implementation from scratch, HID support was heavily inspired by the existing [`go.hid`](https://github.com/GeertJohan/go.hid) library, which seems abandoned since 2015; is incompatible with Go 1.6+; and has various external dependencies. + +Wide character support in the HID support is done via the [`gowchar`](https://github.com/orofarne/gowchar) library, unmaintained since 2013; non buildable with a modern Go release and failing `go vet` checks. As such, `gowchar` was also vendored in inline. + +Error handling for the `libusb` integration originates from the [`gousb`](https://github.com/google/gousb) library. + +## License + +This USB library is licensed under the [GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html) (dictated by libusb). + +If you are only interested in Human Interface devices, a less restrictive package can be found at [`github.com/karalabe/hid`](https://github.com/karalabe/hid). diff --git a/vendor/github.com/karalabe/hid/appveyor.yml b/vendor/github.com/karalabe/usb/appveyor.yml similarity index 75% rename from vendor/github.com/karalabe/hid/appveyor.yml rename to vendor/github.com/karalabe/usb/appveyor.yml index 84b3c95ff..73a9664ae 100644 --- a/vendor/github.com/karalabe/hid/appveyor.yml +++ b/vendor/github.com/karalabe/usb/appveyor.yml @@ -1,7 +1,7 @@ os: Visual Studio 2015 # Clone directly into GOPATH. -clone_folder: C:\gopath\src\github.com\karalabe\hid +clone_folder: C:\gopath\src\github.com\karalabe\usb clone_depth: 1 version: "{branch}.{build}" environment: @@ -22,11 +22,14 @@ environment: install: - rmdir C:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.1.windows-%GOARCH%.zip - - 7z x go1.10.1.windows-%GOARCH%.zip -y -oC:\ > NUL + - appveyor DownloadFile https://storage.googleapis.com/golang/go1.12.9.windows-%GOARCH%.zip + - 7z x go1.12.9.windows-%GOARCH%.zip -y -oC:\ > NUL - go version - gcc --version build_script: - go install ./... - go test -v ./... + - set CGO_ENABLED=0 + - go install ./... + - go test -v ./... diff --git a/vendor/github.com/karalabe/usb/demo.go b/vendor/github.com/karalabe/usb/demo.go new file mode 100644 index 000000000..229faaf5f --- /dev/null +++ b/vendor/github.com/karalabe/usb/demo.go @@ -0,0 +1,76 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// +build none + +package main + +import ( + "fmt" + "strings" + + "github.com/karalabe/usb" +) + +func main() { + // Enumerate all the HID devices in alphabetical path order + hids, err := usb.EnumerateHid(0, 0) + if err != nil { + panic(err) + } + for i := 0; i < len(hids); i++ { + for j := i + 1; j < len(hids); j++ { + if hids[i].Path > hids[j].Path { + hids[i], hids[j] = hids[j], hids[i] + } + } + } + for i, hid := range hids { + fmt.Println(strings.Repeat("-", 128)) + fmt.Printf("HID #%d\n", i) + fmt.Printf(" OS Path: %s\n", hid.Path) + fmt.Printf(" Vendor ID: %#04x\n", hid.VendorID) + fmt.Printf(" Product ID: %#04x\n", hid.ProductID) + fmt.Printf(" Release: %d\n", hid.Release) + fmt.Printf(" Serial: %s\n", hid.Serial) + fmt.Printf(" Manufacturer: %s\n", hid.Manufacturer) + fmt.Printf(" Product: %s\n", hid.Product) + fmt.Printf(" Usage Page: %d\n", hid.UsagePage) + fmt.Printf(" Usage: %d\n", hid.Usage) + fmt.Printf(" Interface: %d\n", hid.Interface) + } + fmt.Println(strings.Repeat("=", 128)) + + // Enumerate all the non-HID devices in alphabetical path order + raws, err := usb.EnumerateRaw(0, 0) + if err != nil { + panic(err) + } + for i := 0; i < len(raws); i++ { + for j := i + 1; j < len(raws); j++ { + if raws[i].Path > raws[j].Path { + raws[i], raws[j] = raws[j], raws[i] + } + } + } + for i, raw := range raws { + fmt.Printf("RAW #%d\n", i) + fmt.Printf(" OS Path: %s\n", raw.Path) + fmt.Printf(" Vendor ID: %#04x\n", raw.VendorID) + fmt.Printf(" Product ID: %#04x\n", raw.ProductID) + fmt.Printf(" Interface: %d\n", raw.Interface) + fmt.Println(strings.Repeat("-", 128)) + } +} diff --git a/vendor/github.com/karalabe/usb/go.mod b/vendor/github.com/karalabe/usb/go.mod new file mode 100644 index 000000000..ef549d28f --- /dev/null +++ b/vendor/github.com/karalabe/usb/go.mod @@ -0,0 +1,3 @@ +module github.com/karalabe/usb + +go 1.12 diff --git a/vendor/github.com/karalabe/usb/hid_disabled.go b/vendor/github.com/karalabe/usb/hid_disabled.go new file mode 100644 index 000000000..a85964bf3 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hid_disabled.go @@ -0,0 +1,42 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2017 The library Authors +// +// This 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 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 library. If not, see . + +// +build !freebsd,!linux,!darwin,!windows ios !cgo + +package usb + +// HidDevice is a live HID USB connected device handle. On platforms that this file +// implements, the type lacks the actual HID device and all methods are noop. +type HidDevice struct { + DeviceInfo // Embed the infos for easier access +} + +// Close releases the HID USB device handle. On platforms that this file implements, +// the method is just a noop. +func (dev *HidDevice) Close() error { + return ErrUnsupportedPlatform +} + +// Write sends an output report to a HID device. On platforms that this file +// implements, the method just returns an error. +func (dev *HidDevice) Write(b []byte) (int, error) { + return 0, ErrUnsupportedPlatform +} + +// Read retrieves an input report from a HID device. On platforms that this file +// implements, the method just returns an error. +func (dev *HidDevice) Read(b []byte) (int, error) { + return 0, ErrUnsupportedPlatform +} diff --git a/vendor/github.com/karalabe/hid/hid_enabled.go b/vendor/github.com/karalabe/usb/hid_enabled.go similarity index 61% rename from vendor/github.com/karalabe/hid/hid_enabled.go rename to vendor/github.com/karalabe/usb/hid_enabled.go index e95e5792d..c2b372098 100644 --- a/vendor/github.com/karalabe/hid/hid_enabled.go +++ b/vendor/github.com/karalabe/usb/hid_enabled.go @@ -1,44 +1,25 @@ -// hid - Gopher Interface Devices (USB HID) -// Copyright (c) 2017 Péter Szilágyi. All rights reserved. +// usb - Self contained USB and HID library for Go +// Copyright 2017 The library Authors // -// This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under LGNU GPL 2.1 or later. +// This 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 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 library. If not, see . -// +build linux,cgo darwin,!ios,cgo windows,cgo +// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo -package hid +package usb /* -#cgo CFLAGS: -I./hidapi/hidapi - -#cgo linux CFLAGS: -I./libusb/libusb -DDEFAULT_VISIBILITY="" -DOS_LINUX -D_GNU_SOURCE -DPOLL_NFDS_TYPE=int -#cgo linux,!android LDFLAGS: -lrt -#cgo darwin CFLAGS: -DOS_DARWIN -#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit -#cgo windows CFLAGS: -DOS_WINDOWS -#cgo windows LDFLAGS: -lsetupapi - -#ifdef OS_LINUX - #include - #include "os/threads_posix.c" - #include "os/poll_posix.c" - - #include "os/linux_usbfs.c" - #include "os/linux_netlink.c" - - #include "core.c" - #include "descriptor.c" - #include "hotplug.c" - #include "io.c" - #include "strerror.c" - #include "sync.c" - - #include "hidapi/libusb/hid.c" -#elif OS_DARWIN - #include "hidapi/mac/hid.c" -#elif OS_WINDOWS - #include "hidapi/windows/hid.c" -#endif +#include +#include "./hidapi/hidapi/hidapi.h" */ import "C" @@ -49,35 +30,16 @@ import ( "unsafe" ) -// enumerateLock is a mutex serializing access to USB device enumeration needed -// by the macOS USB HID system calls, which require 2 consecutive method calls -// for enumeration, causing crashes if called concurrently. -// -// For more details, see: -// https://developer.apple.com/documentation/iokit/1438371-iohidmanagersetdevicematching -// > "subsequent calls will cause the hid manager to release previously enumerated devices" -var enumerateLock sync.Mutex - -// Supported returns whether this platform is supported by the HID library or not. -// The goal of this method is to allow programatically handling platforms that do -// not support USB HID and not having to fall back to build constraints. -func Supported() bool { - return true -} - -// Enumerate returns a list of all the HID devices attached to the system which +// enumerateHid returns a list of all the HID devices attached to the system which // match the vendor and product id: // - If the vendor id is set to 0 then any vendor matches. // - If the product id is set to 0 then any product matches. // - If the vendor and product id are both 0, all HID devices are returned. -func Enumerate(vendorID uint16, productID uint16) []DeviceInfo { - enumerateLock.Lock() - defer enumerateLock.Unlock() - +func enumerateHid(vendorID uint16, productID uint16) ([]DeviceInfo, error) { // Gather all device infos and ensure they are freed before returning head := C.hid_enumerate(C.ushort(vendorID), C.ushort(productID)) if head == nil { - return nil + return nil, nil } defer C.hid_free_enumeration(head) @@ -104,14 +66,11 @@ func Enumerate(vendorID uint16, productID uint16) []DeviceInfo { } infos = append(infos, info) } - return infos + return infos, nil } -// Open connects to an HID device by its path name. -func (info DeviceInfo) Open() (*Device, error) { - enumerateLock.Lock() - defer enumerateLock.Unlock() - +// openHid connects to an HID device by its path name. +func openHid(info DeviceInfo) (*hidDevice, error) { path := C.CString(info.Path) defer C.free(unsafe.Pointer(path)) @@ -119,14 +78,14 @@ func (info DeviceInfo) Open() (*Device, error) { if device == nil { return nil, errors.New("hidapi: failed to open device") } - return &Device{ + return &hidDevice{ DeviceInfo: info, device: device, }, nil } -// Device is a live HID USB connected device handle. -type Device struct { +// hidDevice is a live HID USB connected device handle. +type hidDevice struct { DeviceInfo // Embed the infos for easier access device *C.hid_device // Low level HID device to communicate through @@ -134,7 +93,7 @@ type Device struct { } // Close releases the HID USB device handle. -func (dev *Device) Close() error { +func (dev *hidDevice) Close() error { dev.lock.Lock() defer dev.lock.Unlock() @@ -149,7 +108,7 @@ func (dev *Device) Close() error { // // Write will send the data on the first OUT endpoint, if one exists. If it does // not, it will send the data through the Control Endpoint (Endpoint 0). -func (dev *Device) Write(b []byte) (int, error) { +func (dev *hidDevice) Write(b []byte) (int, error) { // Abort if nothing to write if len(b) == 0 { return 0, nil @@ -192,7 +151,7 @@ func (dev *Device) Write(b []byte) (int, error) { } // Read retrieves an input report from a HID device. -func (dev *Device) Read(b []byte) (int, error) { +func (dev *hidDevice) Read(b []byte) (int, error) { // Aborth if nothing to read if len(b) == 0 { return 0, nil diff --git a/vendor/github.com/karalabe/hid/hidapi/hidapi/hidapi.h b/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h similarity index 99% rename from vendor/github.com/karalabe/hid/hidapi/hidapi/hidapi.h rename to vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h index e5bc2dc40..166f3509a 100644 --- a/vendor/github.com/karalabe/hid/hidapi/hidapi/hidapi.h +++ b/vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h @@ -87,7 +87,7 @@ extern "C" { needed. This function should be called at the beginning of execution however, if there is a chance of HIDAPI handles being opened by different threads simultaneously. - + @ingroup API @returns @@ -388,4 +388,3 @@ extern "C" { #endif #endif - diff --git a/vendor/github.com/karalabe/hid/hidapi/libusb/hid.c b/vendor/github.com/karalabe/usb/hidapi/libusb/hid.c similarity index 100% rename from vendor/github.com/karalabe/hid/hidapi/libusb/hid.c rename to vendor/github.com/karalabe/usb/hidapi/libusb/hid.c diff --git a/vendor/github.com/karalabe/hid/hidapi/mac/hid.c b/vendor/github.com/karalabe/usb/hidapi/mac/hid.c similarity index 100% rename from vendor/github.com/karalabe/hid/hidapi/mac/hid.c rename to vendor/github.com/karalabe/usb/hidapi/mac/hid.c diff --git a/vendor/github.com/karalabe/hid/hidapi/windows/hid.c b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c similarity index 99% rename from vendor/github.com/karalabe/hid/hidapi/windows/hid.c rename to vendor/github.com/karalabe/usb/hidapi/windows/hid.c index 86810d7e5..60da64608 100644 --- a/vendor/github.com/karalabe/hid/hidapi/windows/hid.c +++ b/vendor/github.com/karalabe/usb/hidapi/windows/hid.c @@ -8,7 +8,7 @@ 8/22/2009 Copyright 2009, All Rights Reserved. - + At the discretion of the user of this library, this software may be licensed under the terms of the GNU General Public License v3, a BSD-Style license, or the @@ -74,6 +74,8 @@ extern "C" { #pragma warning(disable:4996) #endif +#pragma GCC diagnostic ignored "-Wstringop-overflow" + #ifdef __cplusplus extern "C" { #endif @@ -181,7 +183,7 @@ static void register_error(hid_device *device, const char *op) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPVOID)&msg, 0/*sz*/, NULL); - + /* Get rid of the CR and LF that FormatMessage() sticks at the end of the message. Thanks Microsoft! */ ptr = msg; @@ -292,9 +294,9 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - + /* Iterate over each device in the HID class, looking for the right one. */ - + for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; @@ -305,7 +307,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor &InterfaceClassGuid, device_index, &device_interface_data); - + if (!res) { /* A return of FALSE from this function means that there are no more devices. */ @@ -377,7 +379,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; - } + } /* Get the Vendor ID and Product ID for this device. */ @@ -421,7 +423,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor HidD_FreePreparsedData(pp_data); } - + /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; @@ -521,7 +523,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; - + devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { @@ -547,7 +549,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi } hid_free_enumeration(devs); - + return handle; } @@ -590,7 +592,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) } nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); + register_error(dev, "HidP_GetCaps"); goto err_pp_data; } dev->output_report_length = caps.OutputReportByteLength; @@ -603,7 +605,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) err_pp_data: HidD_FreePreparsedData(pp_data); -err: +err: free_hid_device(dev); return NULL; } @@ -636,7 +638,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * } res = WriteFile(dev->device_handle, buf, length, NULL, &ol); - + if (!res) { if (GetLastError() != ERROR_IO_PENDING) { /* WriteFile() failed. Return error. */ @@ -679,7 +681,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char memset(dev->read_buf, 0, dev->input_report_length); ResetEvent(ev); res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); - + if (!res) { if (GetLastError() != ERROR_IO_PENDING) { /* ReadFile() has failed. @@ -705,7 +707,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char we are in non-blocking mode. Get the number of bytes read. The actual data has been copied to the data[] array which was passed to ReadFile(). */ res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - + /* Set pending back to false, even if GetOverlappedResult() returned error. */ dev->read_pending = FALSE; @@ -725,13 +727,13 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char memcpy(data, dev->read_buf, copy_len); } } - + end_of_function: if (!res) { register_error(dev, "GetOverlappedResult"); return -1; } - + return copy_len; } @@ -876,7 +878,7 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) /*#define PICPGM*/ /*#define S11*/ #define P32 -#ifdef S11 +#ifdef S11 unsigned short VendorID = 0xa0a0; unsigned short ProductID = 0x0001; #endif @@ -906,7 +908,7 @@ int __cdecl main(int argc, char* argv[]) memset(buf,0x00,sizeof(buf)); buf[0] = 0; buf[1] = 0x81; - + /* Open the device. */ int handle = open(VendorID, ProductID, L"12345"); diff --git a/vendor/github.com/karalabe/usb/libs.go b/vendor/github.com/karalabe/usb/libs.go new file mode 100644 index 000000000..6446acee9 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libs.go @@ -0,0 +1,74 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo + +package usb + +/* +#cgo CFLAGS: -I./hidapi/hidapi +#cgo CFLAGS: -I./libusb/libusb +#cgo CFLAGS: -DDEFAULT_VISIBILITY="" +#cgo CFLAGS: -DPOLL_NFDS_TYPE=int + +#cgo linux CFLAGS: -DOS_LINUX -D_GNU_SOURCE -DHAVE_SYS_TIME_H +#cgo linux,!android LDFLAGS: -lrt +#cgo darwin CFLAGS: -DOS_DARWIN -DHAVE_SYS_TIME_H +#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit -lobjc +#cgo windows CFLAGS: -DOS_WINDOWS +#cgo windows LDFLAGS: -lsetupapi +#cgo freebsd CFLAGS: -DOS_FREEBSD +#cgo freebsd LDFLAGS: -lusb +#cgo openbsd CFLAGS: -DOS_OPENBSD + +#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(DOS_FREEBSD) || defined(OS_OPENBSD) + #include + #include "os/threads_posix.c" + #include "os/poll_posix.c" +#elif defined(OS_WINDOWS) + #include "os/poll_windows.c" + #include "os/threads_windows.c" +#endif + +#ifdef OS_LINUX + #include "os/linux_usbfs.c" + #include "os/linux_netlink.c" + #include "hidapi/libusb/hid.c" +#elif OS_DARWIN + #include "os/darwin_usb.c" + #include "hidapi/mac/hid.c" +#elif OS_WINDOWS + #include "os/windows_nt_common.c" + #include "os/windows_usbdk.c" + #include "os/windows_winusb.c" + #include "hidapi/windows/hid.c" +#elif OS_FREEBSD + #include + #include "hidapi/libusb/hid.c" +#elif DOS_OPENBSD + #include "os/openbsd_usb.c" + #include "hidapi/libusb/hid.c" +#endif + +#ifndef OS_FREEBSD + #include "core.c" + #include "descriptor.c" + #include "hotplug.c" + #include "io.c" + #include "strerror.c" + #include "sync.c" +#endif +*/ +import "C" diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/config.h b/vendor/github.com/karalabe/usb/libusb/libusb/config.h similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/config.h rename to vendor/github.com/karalabe/usb/libusb/libusb/config.h diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/core.c b/vendor/github.com/karalabe/usb/libusb/libusb/core.c similarity index 91% rename from vendor/github.com/karalabe/hid/libusb/libusb/core.c rename to vendor/github.com/karalabe/usb/libusb/libusb/core.c index d45bfe177..50f92f6b1 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/core.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/core.c @@ -44,32 +44,6 @@ #include "libusbi.h" #include "hotplug.h" -#if defined(OS_LINUX) -const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend; -#elif defined(OS_DARWIN) -const struct usbi_os_backend * const usbi_backend = &darwin_backend; -#elif defined(OS_OPENBSD) -const struct usbi_os_backend * const usbi_backend = &openbsd_backend; -#elif defined(OS_NETBSD) -const struct usbi_os_backend * const usbi_backend = &netbsd_backend; -#elif defined(OS_WINDOWS) - -#if defined(USE_USBDK) -const struct usbi_os_backend * const usbi_backend = &usbdk_backend; -#else -const struct usbi_os_backend * const usbi_backend = &windows_backend; -#endif - -#elif defined(OS_WINCE) -const struct usbi_os_backend * const usbi_backend = &wince_backend; -#elif defined(OS_HAIKU) -const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend; -#elif defined (OS_SUNOS) -const struct usbi_os_backend * const usbi_backend = &sunos_backend; -#else -#error "Unsupported OS" -#endif - struct libusb_context *usbi_default_context = NULL; static const struct libusb_version libusb_version_internal = { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, @@ -142,15 +116,17 @@ struct list_head active_contexts_list; * libusb uses stderr for all logging. By default, logging is set to NONE, * which means that no output will be produced. However, unless the library * has been compiled with logging disabled, then any application calls to - * libusb_set_debug(), or the setting of the environmental variable - * LIBUSB_DEBUG outside of the application, can result in logging being - * produced. Your application should therefore not close stderr, but instead - * direct it to the null device if its output is undesirable. + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the + * environmental variable LIBUSB_DEBUG outside of the application, can result + * in logging being produced. Your application should therefore not close + * stderr, but instead direct it to the null device if its output is + * undesirable. * - * The libusb_set_debug() function can be used to enable logging of certain - * messages. Under standard configuration, libusb doesn't really log much - * so you are advised to use this function to enable all error/warning/ - * informational messages. It will help debug problems with your software. + * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be + * used to enable logging of certain messages. Under standard configuration, + * libusb doesn't really log much so you are advised to use this function + * to enable all error/warning/ informational messages. It will help debug + * problems with your software. * * The logged messages are unstructured. There is no one-to-one correspondence * between messages being logged and success or failure return codes from @@ -165,18 +141,20 @@ struct list_head active_contexts_list; * * The LIBUSB_DEBUG environment variable can be used to enable message logging * at run-time. This environment variable should be set to a log level number, - * which is interpreted the same as the libusb_set_debug() parameter. When this + * which is interpreted the same as the + * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_debug() effectively does nothing. + * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does + * nothing. * * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_debug() and the LIBUSB_DEBUG environment - * variable have no effects. + * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) + * and the LIBUSB_DEBUG environment variable have no effects. * * libusb can also be compiled with verbose debugging messages always. When * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_debug() and the LIBUSB_DEBUG environment variable - * have no effects. + * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and + * the LIBUSB_DEBUG environment variable have no effects. * * \section remarks Other remarks * @@ -187,6 +165,20 @@ struct list_head active_contexts_list; /** * \page libusb_caveats Caveats * + * \section fork Fork considerations + * + * libusb is not designed to work across fork() calls. Depending on + * the platform, there may be resources in the parent process that are not + * available to the child (e.g. the hotplug monitor thread on Linux). In + * addition, since the parent and child will share libusb's internal file + * descriptors, using libusb in any way from the child could cause the parent + * process's \ref libusb_context to get into an inconsistent state. + * + * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means + * that it is safe to fork() and exec() without worrying about the child + * process needing to clean up state or having access to these file descriptors. + * Other platforms may not be so forgiving, so consider yourself warned! + * * \section devresets Device resets * * The libusb_reset_device() function allows you to reset a device. If your @@ -291,7 +283,6 @@ if (cfg != desired) * information about the end of the short packet, and the user probably wanted * that surplus data to arrive in the next logical transfer. * - * * \section zlp Zero length packets * * - libusb is able to send a packet of zero length to an endpoint simply by @@ -310,7 +301,7 @@ if (cfg != desired) * developed modules may both use libusb. * * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_debug() calls + * "instances" of libusb will not interfere: libusb_set_option() calls * from one user will not affect the same settings for other users, other * users can continue using libusb after one of them calls libusb_exit(), etc. * @@ -435,6 +426,7 @@ if (cfg != desired) * - libusb_set_debug() * - libusb_set_interface_alt_setting() * - libusb_set_iso_packet_lengths() + * - libusb_set_option() * - libusb_setlocale() * - libusb_set_pollfd_notifiers() * - libusb_strerror() @@ -478,6 +470,7 @@ if (cfg != desired) * - \ref libusb_iso_sync_type * - \ref libusb_iso_usage_type * - \ref libusb_log_level + * - \ref libusb_option * - \ref libusb_request_recipient * - \ref libusb_request_type * - \ref libusb_speed @@ -680,7 +673,7 @@ struct discovered_devs *discovered_devs_append( struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, unsigned long session_id) { - size_t priv_size = usbi_backend->device_priv_size; + size_t priv_size = usbi_backend.device_priv_size; struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size); int r; @@ -824,8 +817,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, /* backend provides hotplug support */ struct libusb_device *dev; - if (usbi_backend->hotplug_poll) - usbi_backend->hotplug_poll(); + if (usbi_backend.hotplug_poll) + usbi_backend.hotplug_poll(); usbi_mutex_lock(&ctx->usb_devs_lock); list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { @@ -839,7 +832,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, usbi_mutex_unlock(&ctx->usb_devs_lock); } else { /* backend does not provide hotplug support */ - r = usbi_backend->get_device_list(ctx, &discdevs); + r = usbi_backend.get_device_list(ctx, &discdevs); } if (r < 0) { @@ -1167,8 +1160,8 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev) libusb_unref_device(dev->parent_dev); - if (usbi_backend->destroy_device) - usbi_backend->destroy_device(dev); + if (usbi_backend.destroy_device) + usbi_backend.destroy_device(dev); if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { /* backend does not support hotplug */ @@ -1242,7 +1235,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, { struct libusb_context *ctx = DEVICE_CTX(dev); struct libusb_device_handle *_dev_handle; - size_t priv_size = usbi_backend->device_handle_priv_size; + size_t priv_size = usbi_backend.device_handle_priv_size; int r; usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); @@ -1265,7 +1258,7 @@ int API_EXPORTED libusb_open(libusb_device *dev, _dev_handle->claimed_interfaces = 0; memset(&_dev_handle->os_priv, 0, priv_size); - r = usbi_backend->open(_dev_handle); + r = usbi_backend.open(_dev_handle); if (r < 0) { usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); libusb_unref_device(dev); @@ -1382,7 +1375,7 @@ static void do_close(struct libusb_context *ctx, list_del(&dev_handle->list); usbi_mutex_unlock(&ctx->open_devs_lock); - usbi_backend->close(dev_handle); + usbi_backend.close(dev_handle); libusb_unref_device(dev_handle->dev); usbi_mutex_destroy(&dev_handle->lock); free(dev_handle); @@ -1491,8 +1484,8 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, int r = LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(""); - if (usbi_backend->get_configuration) - r = usbi_backend->get_configuration(dev_handle, config); + if (usbi_backend.get_configuration) + r = usbi_backend.get_configuration(dev_handle, config); if (r == LIBUSB_ERROR_NOT_SUPPORTED) { uint8_t tmp = 0; @@ -1567,7 +1560,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, int configuration) { usbi_dbg("configuration %d", configuration); - return usbi_backend->set_configuration(dev_handle, configuration); + return usbi_backend.set_configuration(dev_handle, configuration); } /** \ingroup libusb_dev @@ -1614,7 +1607,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, if (dev_handle->claimed_interfaces & (1 << interface_number)) goto out; - r = usbi_backend->claim_interface(dev_handle, interface_number); + r = usbi_backend.claim_interface(dev_handle, interface_number); if (r == 0) dev_handle->claimed_interfaces |= 1 << interface_number; @@ -1657,7 +1650,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, goto out; } - r = usbi_backend->release_interface(dev_handle, interface_number); + r = usbi_backend.release_interface(dev_handle, interface_number); if (r == 0) dev_handle->claimed_interfaces &= ~(1 << interface_number); @@ -1707,7 +1700,7 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand } usbi_mutex_unlock(&dev_handle->lock); - return usbi_backend->set_interface_altsetting(dev_handle, interface_number, + return usbi_backend.set_interface_altsetting(dev_handle, interface_number, alternate_setting); } @@ -1734,7 +1727,7 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->clear_halt(dev_handle, endpoint); + return usbi_backend.clear_halt(dev_handle, endpoint); } /** \ingroup libusb_dev @@ -1762,7 +1755,7 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - return usbi_backend->reset_device(dev_handle); + return usbi_backend.reset_device(dev_handle); } /** \ingroup libusb_asyncio @@ -1794,8 +1787,8 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->alloc_streams) - return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints, + if (usbi_backend.alloc_streams) + return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1821,8 +1814,8 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->free_streams) - return usbi_backend->free_streams(dev_handle, endpoints, + if (usbi_backend.free_streams) + return usbi_backend.free_streams(dev_handle, endpoints, num_endpoints); else return LIBUSB_ERROR_NOT_SUPPORTED; @@ -1859,8 +1852,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl if (!dev_handle->dev->attached) return NULL; - if (usbi_backend->dev_mem_alloc) - return usbi_backend->dev_mem_alloc(dev_handle, length); + if (usbi_backend.dev_mem_alloc) + return usbi_backend.dev_mem_alloc(dev_handle, length); else return NULL; } @@ -1876,8 +1869,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, unsigned char *buffer, size_t length) { - if (usbi_backend->dev_mem_free) - return usbi_backend->dev_mem_free(dev_handle, buffer, length); + if (usbi_backend.dev_mem_free) + return usbi_backend.dev_mem_free(dev_handle, buffer, length); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1907,8 +1900,8 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->kernel_driver_active) - return usbi_backend->kernel_driver_active(dev_handle, interface_number); + if (usbi_backend.kernel_driver_active) + return usbi_backend.kernel_driver_active(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1942,8 +1935,8 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->detach_kernel_driver) - return usbi_backend->detach_kernel_driver(dev_handle, interface_number); + if (usbi_backend.detach_kernel_driver) + return usbi_backend.detach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -1976,8 +1969,8 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, if (!dev_handle->dev->attached) return LIBUSB_ERROR_NO_DEVICE; - if (usbi_backend->attach_kernel_driver) - return usbi_backend->attach_kernel_driver(dev_handle, interface_number); + if (usbi_backend.attach_kernel_driver) + return usbi_backend.attach_kernel_driver(dev_handle, interface_number); else return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -2007,7 +2000,7 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int API_EXPORTED libusb_set_auto_detach_kernel_driver( libusb_device_handle *dev_handle, int enable) { - if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) + if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) return LIBUSB_ERROR_NOT_SUPPORTED; dev_handle->auto_detach_kernel_driver = enable; @@ -2015,37 +2008,100 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver( } /** \ingroup libusb_lib - * Set log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stdout/stderr file descriptors. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - * - * \param ctx the context to operate on, or NULL for the default context - * \param level debug level to set + * \deprecated Use libusb_set_option() instead using the + * \ref LIBUSB_OPTION_LOG_LEVEL option. */ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) { +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) USBI_GET_CONTEXT(ctx); - if (!ctx->debug_fixed) - ctx->debug = level; + if (!ctx->debug_fixed) { + level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + ctx->debug = (enum libusb_log_level)level; + } +#else + UNUSED(ctx); + UNUSED(level); +#endif } +/** \ingroup libusb_lib + * Set an option in the library. + * + * Use this function to configure a specific option within the library. + * + * Some options require one or more arguments to be provided. Consult each + * option's documentation for specific requirements. + * + * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106 + * + * \param ctx context on which to operate + * \param option which option to set + * \param ... any required arguments for the specified option + * + * \returns LIBUSB_SUCCESS on success + * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported + * on this platform + */ +int API_EXPORTED libusb_set_option(libusb_context *ctx, + enum libusb_option option, ...) +{ + int arg, r = LIBUSB_SUCCESS; + va_list ap; + + USBI_GET_CONTEXT(ctx); + + va_start(ap, option); + switch (option) { + case LIBUSB_OPTION_LOG_LEVEL: + arg = va_arg(ap, int); + if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) { + r = LIBUSB_ERROR_INVALID_PARAM; + break; + } +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + if (!ctx->debug_fixed) + ctx->debug = (enum libusb_log_level)arg; +#endif + break; + + /* Handle all backend-specific options here */ + case LIBUSB_OPTION_USE_USBDK: + if (usbi_backend.set_option) + r = usbi_backend.set_option(ctx, option, ap); + else + r = LIBUSB_ERROR_NOT_SUPPORTED; + break; + + default: + r = LIBUSB_ERROR_INVALID_PARAM; + } + va_end(ap); + + return r; +} + +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) +/* returns the log level as defined in the LIBUSB_DEBUG environment variable. + * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE. + * value is clamped to ensure it is within the valid range of possibilities. + */ +static enum libusb_log_level get_env_debug_level(void) +{ + const char *dbg = getenv("LIBUSB_DEBUG"); + enum libusb_log_level level; + if (dbg) { + int dbg_level = atoi(dbg); + dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG); + level = (enum libusb_log_level)dbg_level; + } else { + level = LIBUSB_LOG_LEVEL_NONE; + } + return level; +} +#endif + /** \ingroup libusb_lib * Initialize libusb. This function must be called before calling any other * libusb function. @@ -2062,7 +2118,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) int API_EXPORTED libusb_init(libusb_context **context) { struct libusb_device *dev, *next; - char *dbg = getenv("LIBUSB_DEBUG"); + size_t priv_size = usbi_backend.context_priv_size; struct libusb_context *ctx; static int first_init = 1; int r = 0; @@ -2070,7 +2126,7 @@ int API_EXPORTED libusb_init(libusb_context **context) usbi_mutex_static_lock(&default_context_lock); if (!timestamp_origin.tv_sec) { - usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); } if (!context && usbi_default_context) { @@ -2080,22 +2136,18 @@ int API_EXPORTED libusb_init(libusb_context **context) return 0; } - ctx = calloc(1, sizeof(*ctx)); + ctx = calloc(1, sizeof(*ctx) + priv_size); if (!ctx) { r = LIBUSB_ERROR_NO_MEM; goto err_unlock; } -#ifdef ENABLE_DEBUG_LOGGING - ctx->debug = LIBUSB_LOG_LEVEL_DEBUG; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + ctx->debug = get_env_debug_level(); + if (ctx->debug != LIBUSB_LOG_LEVEL_NONE) + ctx->debug_fixed = 1; #endif - if (dbg) { - ctx->debug = atoi(dbg); - if (ctx->debug) - ctx->debug_fixed = 1; - } - /* default context should be initialized before calling usbi_dbg */ if (!usbi_default_context) { usbi_default_context = ctx; @@ -2112,6 +2164,7 @@ int API_EXPORTED libusb_init(libusb_context **context) list_init(&ctx->usb_devs); list_init(&ctx->open_devs); list_init(&ctx->hotplug_cbs); + ctx->next_hotplug_cb_handle = 1; usbi_mutex_static_lock(&active_contexts_lock); if (first_init) { @@ -2121,8 +2174,8 @@ int API_EXPORTED libusb_init(libusb_context **context) list_add (&ctx->list, &active_contexts_list); usbi_mutex_static_unlock(&active_contexts_lock); - if (usbi_backend->init) { - r = usbi_backend->init(ctx); + if (usbi_backend.init) { + r = usbi_backend.init(ctx); if (r) goto err_free_ctx; } @@ -2139,8 +2192,8 @@ int API_EXPORTED libusb_init(libusb_context **context) return 0; err_backend_exit: - if (usbi_backend->exit) - usbi_backend->exit(); + if (usbi_backend.exit) + usbi_backend.exit(ctx); err_free_ctx: if (ctx == usbi_default_context) { usbi_default_context = NULL; @@ -2200,7 +2253,7 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) usbi_mutex_static_unlock(&active_contexts_lock); if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_hotplug_deregister_all(ctx); + usbi_hotplug_deregister(ctx, 1); /* * Ensure any pending unplug events are read from the hotplug @@ -2230,8 +2283,8 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) usbi_warn(ctx, "application left some devices open"); usbi_io_exit(ctx); - if (usbi_backend->exit) - usbi_backend->exit(); + if (usbi_backend.exit) + usbi_backend.exit(ctx); usbi_mutex_destroy(&ctx->open_devs_lock); usbi_mutex_destroy(&ctx->usb_devs_lock); @@ -2253,15 +2306,17 @@ int API_EXPORTED libusb_has_capability(uint32_t capability) case LIBUSB_CAP_HAS_CAPABILITY: return 1; case LIBUSB_CAP_HAS_HOTPLUG: - return !(usbi_backend->get_device_list); + return !(usbi_backend.get_device_list); case LIBUSB_CAP_HAS_HID_ACCESS: - return (usbi_backend->caps & USBI_CAP_HAS_HID_ACCESS); + return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS); case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: - return (usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); + return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); } return 0; } +#ifdef ENABLE_LOGGING + /* this is defined in libusbi.h if needed */ #ifdef LIBUSB_PRINTF_WIN32 /* @@ -2301,10 +2356,9 @@ int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap) return ret; } -#endif +#endif /* LIBUSB_PRINTF_WIN32 */ -static void usbi_log_str(struct libusb_context *ctx, - enum libusb_log_level level, const char * str) +static void usbi_log_str(enum libusb_log_level level, const char *str) { #if defined(USE_SYSTEM_LOGGING_FACILITY) #if defined(OS_WINDOWS) @@ -2317,18 +2371,20 @@ static void usbi_log_str(struct libusb_context *ctx, #elif defined(__ANDROID__) int priority = ANDROID_LOG_UNKNOWN; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; + case LIBUSB_LOG_LEVEL_NONE: return; case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break; + case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; + case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break; } __android_log_write(priority, "libusb", str); #elif defined(HAVE_SYSLOG_FUNC) int syslog_level = LOG_INFO; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; + case LIBUSB_LOG_LEVEL_NONE: return; case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break; + case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; + case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break; } syslog(syslog_level, "%s", str); @@ -2339,14 +2395,13 @@ static void usbi_log_str(struct libusb_context *ctx, #else fputs(str, stderr); #endif /* USE_SYSTEM_LOGGING_FACILITY */ - UNUSED(ctx); UNUSED(level); } void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, const char *function, const char *format, va_list args) { - const char *prefix = ""; + const char *prefix; char buf[USBI_MAX_LOG_LEN]; struct timespec now; int global_debug, header_len, text_len; @@ -2356,18 +2411,15 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, global_debug = 1; UNUSED(ctx); #else - int ctx_level = 0; + enum libusb_log_level ctx_level = LIBUSB_LOG_LEVEL_NONE; USBI_GET_CONTEXT(ctx); - if (ctx) { + if (ctx) ctx_level = ctx->debug; - } else { - char *dbg = getenv("LIBUSB_DEBUG"); - if (dbg) - ctx_level = atoi(dbg); - } - global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); - if (!ctx_level) + else + ctx_level = get_env_debug_level(); + + if (ctx_level == LIBUSB_LOG_LEVEL_NONE) return; if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING) return; @@ -2375,13 +2427,15 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, return; if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG) return; + + global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); #endif - usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &now); + usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &now); if ((global_debug) && (!has_debug_header_been_displayed)) { has_debug_header_been_displayed = 1; - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); + usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); } if (now.tv_nsec < timestamp_origin.tv_nsec) { now.tv_sec--; @@ -2391,20 +2445,20 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, now.tv_nsec -= timestamp_origin.tv_nsec; switch (level) { - case LIBUSB_LOG_LEVEL_INFO: - prefix = "info"; + case LIBUSB_LOG_LEVEL_NONE: + return; + case LIBUSB_LOG_LEVEL_ERROR: + prefix = "error"; break; case LIBUSB_LOG_LEVEL_WARNING: prefix = "warning"; break; - case LIBUSB_LOG_LEVEL_ERROR: - prefix = "error"; + case LIBUSB_LOG_LEVEL_INFO: + prefix = "info"; break; case LIBUSB_LOG_LEVEL_DEBUG: prefix = "debug"; break; - case LIBUSB_LOG_LEVEL_NONE: - return; default: prefix = "unknown"; break; @@ -2439,7 +2493,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, } strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); - usbi_log_str(ctx, level, buf); + usbi_log_str(level, buf); } void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, @@ -2452,6 +2506,8 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, va_end (args); } +#endif /* ENABLE_LOGGING */ + /** \ingroup libusb_misc * Returns a constant NULL-terminated string with the ASCII name of a libusb * error or transfer status code. The caller must not free() the returned diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/descriptor.c b/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c similarity index 98% rename from vendor/github.com/karalabe/hid/libusb/libusb/descriptor.c rename to vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c index 4c9435fff..74d6de557 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/descriptor.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c @@ -333,7 +333,7 @@ static int parse_interface(libusb_context *ctx, goto err; if (r == 0) { ifp->bNumEndpoints = (uint8_t)i; - break;; + break; } buffer += r; @@ -513,7 +513,7 @@ int usbi_device_cache_descriptor(libusb_device *dev) { int r, host_endian = 0; - r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, + r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, &host_endian); if (r < 0) return r; @@ -572,7 +572,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, int host_endian = 0; int r; - r = usbi_backend->get_active_config_descriptor(dev, tmp, + r = usbi_backend.get_active_config_descriptor(dev, tmp, LIBUSB_DT_CONFIG_SIZE, &host_endian); if (r < 0) return r; @@ -587,7 +587,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, if (!buf) return LIBUSB_ERROR_NO_MEM; - r = usbi_backend->get_active_config_descriptor(dev, buf, + r = usbi_backend.get_active_config_descriptor(dev, buf, _config.wTotalLength, &host_endian); if (r >= 0) r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); @@ -625,7 +625,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, if (config_index >= dev->num_configurations) return LIBUSB_ERROR_NOT_FOUND; - r = usbi_backend->get_config_descriptor(dev, config_index, tmp, + r = usbi_backend.get_config_descriptor(dev, config_index, tmp, LIBUSB_DT_CONFIG_SIZE, &host_endian); if (r < 0) return r; @@ -640,7 +640,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, if (!buf) return LIBUSB_ERROR_NO_MEM; - r = usbi_backend->get_config_descriptor(dev, config_index, buf, + r = usbi_backend.get_config_descriptor(dev, config_index, buf, _config.wTotalLength, &host_endian); if (r >= 0) r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); @@ -663,7 +663,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev, for (i = 0; i < dev->num_configurations; i++) { unsigned char tmp[6]; int host_endian; - int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp), + int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp), &host_endian); if (r < 0) { *idx = -1; @@ -702,8 +702,8 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, int r, idx, host_endian; unsigned char *buf = NULL; - if (usbi_backend->get_config_descriptor_by_value) { - r = usbi_backend->get_config_descriptor_by_value(dev, + if (usbi_backend.get_config_descriptor_by_value) { + r = usbi_backend.get_config_descriptor_by_value(dev, bConfigurationValue, &buf, &host_endian); if (r < 0) return r; @@ -1176,7 +1176,8 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha if (tbuf[0] > r) return LIBUSB_ERROR_IO; - for (di = 0, si = 2; si < tbuf[0]; si += 2) { + di = 0; + for (si = 2; si < tbuf[0]; si += 2) { if (di >= (length - 1)) break; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/hotplug.c b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c similarity index 76% rename from vendor/github.com/karalabe/hid/libusb/libusb/hotplug.c rename to vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c index bbfd6e79a..a4320bc42 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/hotplug.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c @@ -154,36 +154,30 @@ int main (void) { \endcode */ -static int usbi_hotplug_match_cb (struct libusb_context *ctx, +static int usbi_hotplug_match_cb(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, struct libusb_hotplug_callback *hotplug_cb) { - /* Handle lazy deregistration of callback */ - if (hotplug_cb->needs_free) { - /* Free callback */ - return 1; - } - - if (!(hotplug_cb->events & event)) { + if (!(hotplug_cb->flags & event)) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id && + if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) && hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id && + if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) && hotplug_cb->product_id != dev->device_descriptor.idProduct) { return 0; } - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class && + if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) && hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { return 0; } - return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data); + return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data); } void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, @@ -195,8 +189,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, usbi_mutex_lock(&ctx->hotplug_cbs_lock); list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) { + /* process deregistration in usbi_hotplug_deregister() */ + continue; + } + usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb); + ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb); usbi_mutex_lock(&ctx->hotplug_cbs_lock); if (ret) { @@ -206,15 +205,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, } usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - /* the backend is expected to call the callback for each active transfer */ } void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event) { int pending_events; - libusb_hotplug_message *message = calloc(1, sizeof(*message)); + struct libusb_hotplug_message *message = calloc(1, sizeof(*message)); if (!message) { usbi_err(ctx, "error allocating hotplug message"); @@ -240,59 +237,70 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *callback_handle) { - libusb_hotplug_callback *new_callback; - static int handle_id = 1; - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return LIBUSB_ERROR_NOT_SUPPORTED; - } + struct libusb_hotplug_callback *new_callback; /* check for sane values */ - if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || + if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) || + (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) || + (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || !cb_fn) { return LIBUSB_ERROR_INVALID_PARAM; } + /* check for hotplug support */ + if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { + return LIBUSB_ERROR_NOT_SUPPORTED; + } + USBI_GET_CONTEXT(ctx); - new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback)); + new_callback = calloc(1, sizeof(*new_callback)); if (!new_callback) { return LIBUSB_ERROR_NO_MEM; } - new_callback->ctx = ctx; - new_callback->vendor_id = vendor_id; - new_callback->product_id = product_id; - new_callback->dev_class = dev_class; - new_callback->flags = flags; - new_callback->events = events; + new_callback->flags = (uint8_t)events; + if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) { + new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID; + new_callback->vendor_id = (uint16_t)vendor_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) { + new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID; + new_callback->product_id = (uint16_t)product_id; + } + if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) { + new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID; + new_callback->dev_class = (uint8_t)dev_class; + } new_callback->cb = cb_fn; new_callback->user_data = user_data; - new_callback->needs_free = 0; usbi_mutex_lock(&ctx->hotplug_cbs_lock); - /* protect the handle by the context hotplug lock. it doesn't matter if the same handle - * is used for different contexts only that the handle is unique for this context */ - new_callback->handle = handle_id++; + /* protect the handle by the context hotplug lock */ + new_callback->handle = ctx->next_hotplug_cb_handle++; + + /* handle the unlikely case of overflow */ + if (ctx->next_hotplug_cb_handle < 0) + ctx->next_hotplug_cb_handle = 1; list_add(&new_callback->list, &ctx->hotplug_cbs); usbi_mutex_unlock(&ctx->hotplug_cbs_lock); + usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle); - if (flags & LIBUSB_HOTPLUG_ENUMERATE) { - int i, len; + if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) { + ssize_t i, len; struct libusb_device **devs; - len = (int) libusb_get_device_list(ctx, &devs); + len = libusb_get_device_list(ctx, &devs); if (len < 0) { libusb_hotplug_deregister_callback(ctx, new_callback->handle); - return len; + return (int)len; } for (i = 0; i < len; i++) { @@ -311,10 +319,11 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, return LIBUSB_SUCCESS; } -void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, +void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx, libusb_hotplug_callback_handle callback_handle) { struct libusb_hotplug_callback *hotplug_cb; + int deregistered = 0; /* check for hotplug support */ if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { @@ -323,28 +332,42 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx USBI_GET_CONTEXT(ctx); + usbi_dbg("deregister hotplug cb %d", callback_handle); + usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { + list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { if (callback_handle == hotplug_cb->handle) { /* Mark this callback for deregistration */ - hotplug_cb->needs_free = 1; + hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE; + deregistered = 1; } } usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - usbi_hotplug_notification(ctx, NULL, 0); + if (deregistered) { + int pending_events; + + usbi_mutex_lock(&ctx->event_data_lock); + pending_events = usbi_pending_events(ctx); + ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + if (!pending_events) + usbi_signal_event(ctx); + usbi_mutex_unlock(&ctx->event_data_lock); + } } -void usbi_hotplug_deregister_all(struct libusb_context *ctx) { +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced) +{ struct libusb_hotplug_callback *hotplug_cb, *next; usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { - list_del(&hotplug_cb->list); - free(hotplug_cb); + list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { + if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) { + usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb, + hotplug_cb->handle); + list_del(&hotplug_cb->list); + free(hotplug_cb); + } } - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); } diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/hotplug.h b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h similarity index 65% rename from vendor/github.com/karalabe/hid/libusb/libusb/hotplug.h rename to vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h index 2bec81b06..dbadbcb93 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/hotplug.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h @@ -19,12 +19,34 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#if !defined(USBI_HOTPLUG_H) +#ifndef USBI_HOTPLUG_H #define USBI_HOTPLUG_H -#ifndef LIBUSBI_H #include "libusbi.h" -#endif + +enum usbi_hotplug_flags { + /* This callback is interested in device arrivals */ + USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, + + /* This callback is interested in device removals */ + USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + + /* IMPORTANT: The values for the below entries must start *after* + * the highest value of the above entries!!! + */ + + /* The vendor_id field is valid for matching */ + USBI_HOTPLUG_VENDOR_ID_VALID = (1 << 3), + + /* The product_id field is valid for matching */ + USBI_HOTPLUG_PRODUCT_ID_VALID = (1 << 4), + + /* The dev_class field is valid for matching */ + USBI_HOTPLUG_DEV_CLASS_VALID = (1 << 5), + + /* This callback has been unregistered and needs to be freed */ + USBI_HOTPLUG_NEEDS_FREE = (1 << 6), +}; /** \ingroup hotplug * The hotplug callback structure. The user populates this structure with @@ -32,23 +54,17 @@ * to receive notification of hotplug events. */ struct libusb_hotplug_callback { - /** Context this callback is associated with */ - struct libusb_context *ctx; + /** Flags that control how this callback behaves */ + uint8_t flags; - /** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int vendor_id; + /** Vendor ID to match (if flags says this is valid) */ + uint16_t vendor_id; - /** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int product_id; + /** Product ID to match (if flags says this is valid) */ + uint16_t product_id; - /** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int dev_class; - - /** Hotplug callback flags */ - libusb_hotplug_flag flags; - - /** Event(s) that will trigger this callback */ - libusb_hotplug_event events; + /** Device class to match (if flags says this is valid) */ + uint8_t dev_class; /** Callback function to invoke for matching event/device */ libusb_hotplug_callback_fn cb; @@ -59,15 +75,10 @@ struct libusb_hotplug_callback { /** User data that will be passed to the callback function */ void *user_data; - /** Callback is marked for deletion */ - int needs_free; - /** List this callback is registered in (ctx->hotplug_cbs) */ struct list_head list; }; -typedef struct libusb_hotplug_callback libusb_hotplug_callback; - struct libusb_hotplug_message { /** The hotplug event that occurred */ libusb_hotplug_event event; @@ -79,9 +90,7 @@ struct libusb_hotplug_message { struct list_head list; }; -typedef struct libusb_hotplug_message libusb_hotplug_message; - -void usbi_hotplug_deregister_all(struct libusb_context *ctx); +void usbi_hotplug_deregister(struct libusb_context *ctx, int forced); void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event); void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/io.c b/vendor/github.com/karalabe/usb/libusb/libusb/io.c similarity index 98% rename from vendor/github.com/karalabe/hid/libusb/libusb/io.c rename to vendor/github.com/karalabe/usb/libusb/libusb/io.c index eb1eabf1c..a03bfaae1 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/io.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/io.c @@ -1144,8 +1144,8 @@ int usbi_io_init(struct libusb_context *ctx) goto err_close_pipe; #ifdef USBI_TIMERFD_AVAILABLE - ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), - TFD_NONBLOCK); + ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(), + TFD_NONBLOCK | TFD_CLOEXEC); if (ctx->timerfd >= 0) { usbi_dbg("using timerfd for timeouts"); r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); @@ -1205,10 +1205,12 @@ static int calculate_timeout(struct usbi_transfer *transfer) unsigned int timeout = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; - if (!timeout) + if (!timeout) { + timerclear(&transfer->timeout); return 0; + } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); if (r < 0) { usbi_err(ITRANSFER_CTX(transfer), "failed to read monotonic clock, errno=%d", errno); @@ -1255,7 +1257,7 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( int iso_packets) { struct libusb_transfer *transfer; - size_t os_alloc_size = usbi_backend->transfer_priv_size; + size_t os_alloc_size = usbi_backend.transfer_priv_size; size_t alloc_size = sizeof(struct usbi_transfer) + sizeof(struct libusb_transfer) + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) @@ -1526,7 +1528,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) */ usbi_mutex_unlock(&ctx->flying_transfers_lock); - r = usbi_backend->submit_transfer(itransfer); + r = usbi_backend.submit_transfer(itransfer); if (r == LIBUSB_SUCCESS) { itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; /* keep a reference to this device */ @@ -1567,7 +1569,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) r = LIBUSB_ERROR_NOT_FOUND; goto out; } - r = usbi_backend->cancel_transfer(itransfer); + r = usbi_backend.cancel_transfer(itransfer); if (r < 0) { if (r != LIBUSB_ERROR_NOT_FOUND && r != LIBUSB_ERROR_NO_DEVICE) @@ -2004,7 +2006,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx) return 0; /* get current time */ - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); if (r < 0) return r; @@ -2077,7 +2079,6 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) struct pollfd *fds = NULL; int i = -1; int timeout_ms; - int special_event; /* prevent attempts to recursively handle events (e.g. calling into * libusb_handle_events() from within a hotplug or transfer callback) */ @@ -2146,32 +2147,30 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) if (tv->tv_usec % 1000) timeout_ms++; -redo_poll: usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); r = usbi_poll(fds, nfds, timeout_ms); usbi_dbg("poll() returned %d", r); if (r == 0) { r = handle_timeouts(ctx); goto done; - } - else if (r == -1 && errno == EINTR) { + } else if (r == -1 && errno == EINTR) { r = LIBUSB_ERROR_INTERRUPTED; goto done; - } - else if (r < 0) { + } else if (r < 0) { usbi_err(ctx, "poll failed %d err=%d", r, errno); r = LIBUSB_ERROR_IO; goto done; } - special_event = 0; - /* fds[0] is always the event pipe */ if (fds[0].revents) { - libusb_hotplug_message *message = NULL; + struct list_head hotplug_msgs; struct usbi_transfer *itransfer; + int hotplug_cb_deregistered = 0; int ret = 0; + list_init(&hotplug_msgs); + usbi_dbg("caught a fish on the event pipe"); /* take the the event data lock while processing events */ @@ -2186,6 +2185,12 @@ redo_poll: ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; } + if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) { + usbi_dbg("someone unregistered a hotplug cb"); + ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED; + hotplug_cb_deregistered = 1; + } + /* check if someone is closing a device */ if (ctx->device_close) usbi_dbg("someone is closing a device"); @@ -2193,9 +2198,7 @@ redo_poll: /* check for any pending hotplug messages */ if (!list_empty(&ctx->hotplug_msgs)) { usbi_dbg("hotplug message received"); - special_event = 1; - message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list); - list_del(&message->list); + list_cut(&hotplug_msgs, &ctx->hotplug_msgs); } /* complete any pending transfers */ @@ -2203,7 +2206,7 @@ redo_poll: itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); list_del(&itransfer->completed_list); usbi_mutex_unlock(&ctx->event_data_lock); - ret = usbi_backend->handle_transfer_completion(itransfer); + ret = usbi_backend.handle_transfer_completion(itransfer); if (ret) usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); usbi_mutex_lock(&ctx->event_data_lock); @@ -2215,14 +2218,21 @@ redo_poll: usbi_mutex_unlock(&ctx->event_data_lock); - /* process the hotplug message, if any */ - if (message) { + if (hotplug_cb_deregistered) + usbi_hotplug_deregister(ctx, 0); + + /* process the hotplug messages, if any */ + while (!list_empty(&hotplug_msgs)) { + struct libusb_hotplug_message *message = + list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list); + usbi_hotplug_match(ctx, message->device, message->event); /* the device left, dereference the device */ if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) libusb_unref_device(message->device); + list_del(&message->list); free(message); } @@ -2233,7 +2243,7 @@ redo_poll: } if (0 == --r) - goto handled; + goto done; } #ifdef USBI_TIMERFD_AVAILABLE @@ -2242,7 +2252,6 @@ redo_poll: /* timerfd indicates that a timeout has expired */ int ret; usbi_dbg("timerfd triggered"); - special_event = 1; ret = handle_timerfd_trigger(ctx); if (ret < 0) { @@ -2252,20 +2261,14 @@ redo_poll: } if (0 == --r) - goto handled; + goto done; } #endif - r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); + r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); if (r) usbi_err(ctx, "backend handle_events failed with error %d", r); -handled: - if (r == 0 && special_event) { - timeout_ms = 0; - goto redo_poll; - } - done: usbi_end_event_handling(ctx); return r; @@ -2583,7 +2586,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, return 0; } - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); + r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); if (r < 0) { usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); return 0; @@ -2811,7 +2814,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); usbi_mutex_lock(&to_cancel->lock); - usbi_backend->clear_transfer_priv(to_cancel); + usbi_backend.clear_transfer_priv(to_cancel); usbi_mutex_unlock(&to_cancel->lock); usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); } diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/libusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h similarity index 96% rename from vendor/github.com/karalabe/hid/libusb/libusb/libusb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/libusb.h index c562690f9..430136b2e 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/libusb.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/libusb.h @@ -54,13 +54,19 @@ typedef unsigned __int32 uint32_t; #include #endif -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) +#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) #include #endif #include #include +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#else +#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif + /* 'interface' might be defined as a macro on Windows, so we need to * undefine it so as not to break the current libusb API, because * libusb_config_descriptor has an 'interface' member @@ -79,6 +85,8 @@ typedef unsigned __int32 uint32_t; #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #define LIBUSB_DEPRECATED_FOR(f) \ __attribute__((deprecated("Use " #f " instead"))) +#elif __GNUC__ >= 3 +#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated)) #else #define LIBUSB_DEPRECATED_FOR(f) #endif /* __GNUC__ */ @@ -141,7 +149,7 @@ typedef unsigned __int32 uint32_t; * Internally, LIBUSB_API_VERSION is defined as follows: * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) */ -#define LIBUSB_API_VERSION 0x01000105 +#define LIBUSB_API_VERSION 0x01000106 /* The following is kept for compatibility, but will be deprecated in the future */ #define LIBUSBX_API_VERSION LIBUSB_API_VERSION @@ -729,13 +737,7 @@ struct libusb_bos_dev_capability_descriptor { /** Device Capability type */ uint8_t bDevCapabilityType; /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_desc @@ -760,13 +762,7 @@ struct libusb_bos_descriptor { uint8_t bNumDeviceCaps; /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_desc @@ -927,7 +923,7 @@ struct libusb_version { * sessions allows for your program to use two libraries (or dynamically * load two modules) which both independently use libusb. This will prevent * interference between the individual libusb users - for example - * libusb_set_debug() will not affect the other user of the library, and + * libusb_set_option() will not affect the other user of the library, and * libusb_exit() will not destroy resources that the other user is still * using. * @@ -987,6 +983,9 @@ enum libusb_speed { /** The device is operating at super speed (5000MBit/s). */ LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5, }; /** \ingroup libusb_dev @@ -1256,13 +1255,7 @@ struct libusb_transfer { int num_iso_packets; /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; }; /** \ingroup libusb_misc @@ -1290,21 +1283,20 @@ enum libusb_capability { * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, - * warnings and errors to stderr + * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stderr + * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stderr */ enum libusb_log_level { LIBUSB_LOG_LEVEL_NONE = 0, - LIBUSB_LOG_LEVEL_ERROR, - LIBUSB_LOG_LEVEL_WARNING, - LIBUSB_LOG_LEVEL_INFO, - LIBUSB_LOG_LEVEL_DEBUG, + LIBUSB_LOG_LEVEL_ERROR = 1, + LIBUSB_LOG_LEVEL_WARNING = 2, + LIBUSB_LOG_LEVEL_INFO = 3, + LIBUSB_LOG_LEVEL_DEBUG = 4, }; int LIBUSB_CALL libusb_init(libusb_context **ctx); void LIBUSB_CALL libusb_exit(libusb_context *ctx); +LIBUSB_DEPRECATED_FOR(libusb_set_option) void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); const struct libusb_version * LIBUSB_CALL libusb_get_version(void); int LIBUSB_CALL libusb_has_capability(uint32_t capability); @@ -2001,6 +1993,45 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle); +/** \ingroup libusb_lib + * Available option values for libusb_set_option(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + LIBUSB_OPTION_USE_USBDK, +}; + +int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); + #ifdef __cplusplus } #endif diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/libusbi.h b/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h similarity index 94% rename from vendor/github.com/karalabe/hid/libusb/libusb/libusbi.h rename to vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h index 752e39887..31d6ce98d 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/libusbi.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h @@ -39,6 +39,20 @@ #include "libusb.h" #include "version.h" +/* Attribute to ensure that a structure member is aligned to a natural + * pointer alignment. Used for os_priv member. */ +#if defined(_MSC_VER) +#if defined(_WIN64) +#define PTR_ALIGNED __declspec(align(8)) +#else +#define PTR_ALIGNED __declspec(align(4)) +#endif +#elif defined(__GNUC__) +#define PTR_ALIGNED __attribute__((aligned(sizeof(void *)))) +#else +#define PTR_ALIGNED +#endif + /* Inside the libusb code, mark all public functions as follows: * return_type API_EXPORTED function_name(params) { ... } * But if the function returns a pointer, mark it as follows: @@ -139,6 +153,19 @@ static inline void list_del(struct list_head *entry) entry->next = entry->prev = NULL; } +static inline void list_cut(struct list_head *list, struct list_head *head) +{ + if (list_empty(head)) + return; + + list->next = head->next; + list->next->prev = list; + list->prev = head->prev; + list->prev->next = list; + + list_init(head); +} + static inline void *usbi_reallocf(void *ptr, size_t size) { void *ret = realloc(ptr, size); @@ -151,6 +178,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size) const typeof( ((type *)0)->member ) *mptr = (ptr); \ (type *)( (char *)mptr - offsetof(type,member) );}) +#ifndef CLAMP +#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val))) +#endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif @@ -175,29 +205,33 @@ static inline void *usbi_reallocf(void *ptr, size_t size) } while (0) #endif +#ifdef ENABLE_LOGGING + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf usbi_snprintf +#define vsnprintf usbi_vsnprintf +int usbi_snprintf(char *dst, size_t size, const char *format, ...); +int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); +#define LIBUSB_PRINTF_WIN32 +#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */ + void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, const char *function, const char *format, ...); void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, const char *function, const char *format, va_list args); -#if !defined(_MSC_VER) || _MSC_VER >= 1400 +#if !defined(_MSC_VER) || (_MSC_VER >= 1400) -#ifdef ENABLE_LOGGING #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) -#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) -#else -#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0) -#define usbi_dbg(...) do {} while(0) -#endif -#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) -#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) #define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) +#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) +#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) +#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) -#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ +#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ -#ifdef ENABLE_LOGGING #define LOG_BODY(ctxt, level) \ { \ va_list args; \ @@ -205,24 +239,26 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, usbi_log_v(ctxt, level, "", format, args); \ va_end(args); \ } -#else -#define LOG_BODY(ctxt, level) \ -{ \ - (void)(ctxt); \ -} -#endif -static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) -static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) - +static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) +static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) + LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) static inline void usbi_dbg(const char *format, ...) LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) -#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ +#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */ + +#else /* ENABLE_LOGGING */ + +#define usbi_err(ctx, ...) do { (void)ctx; } while (0) +#define usbi_warn(ctx, ...) do { (void)ctx; } while (0) +#define usbi_info(ctx, ...) do { (void)ctx; } while (0) +#define usbi_dbg(...) do {} while (0) + +#endif /* ENABLE_LOGGING */ #define USBI_GET_CONTEXT(ctx) \ do { \ @@ -254,8 +290,10 @@ extern struct libusb_context *usbi_default_context; struct pollfd; struct libusb_context { - int debug; +#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING) + enum libusb_log_level debug; int debug_fixed; +#endif /* internal event pipe, used for signalling occurrence of an internal event. */ int event_pipe[2]; @@ -270,6 +308,7 @@ struct libusb_context { /* A list of registered hotplug callbacks */ struct list_head hotplug_cbs; + libusb_hotplug_callback_handle next_hotplug_cb_handle; usbi_mutex_t hotplug_cbs_lock; /* this is a list of in-flight transfer handles, sorted by timeout @@ -331,6 +370,8 @@ struct libusb_context { #endif struct list_head list; + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; enum usbi_event_flags { @@ -339,6 +380,9 @@ enum usbi_event_flags { /* The user has interrupted the event handler */ USBI_EVENT_USER_INTERRUPT = 1 << 1, + + /* A hotplug callback deregistration is pending */ + USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1 << 2, }; /* Macros for managing event handling state */ @@ -383,17 +427,7 @@ struct libusb_device { struct libusb_device_descriptor device_descriptor; int attached; - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; struct libusb_device_handle { @@ -404,17 +438,8 @@ struct libusb_device_handle { struct list_head list; struct libusb_device *dev; int auto_detach_kernel_driver; - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif + + PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY]; }; enum { @@ -540,14 +565,6 @@ int usbi_clear_event(struct libusb_context *ctx); #include "os/poll_windows.h" #endif -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define snprintf usbi_snprintf -#define vsnprintf usbi_vsnprintf -int usbi_snprintf(char *dst, size_t size, const char *format, ...); -int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); -#define LIBUSB_PRINTF_WIN32 -#endif - struct usbi_pollfd { /* must come first */ struct libusb_pollfd pollfd; @@ -568,13 +585,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd); struct discovered_devs { size_t len; size_t capacity; - struct libusb_device *devices -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; + struct libusb_device *devices[ZERO_SIZED_ARRAY]; }; struct discovered_devs *discovered_devs_append( @@ -607,7 +618,17 @@ struct usbi_os_backend { * * This function is called when the user deinitializes the library. */ - void (*exit)(void); + void (*exit)(struct libusb_context *ctx); + + /* Set a backend-specific option. Optional. + * + * This function is called when the user calls libusb_set_option() and + * the option is not handled by the core library. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*set_option)(struct libusb_context *ctx, enum libusb_option option, + va_list args); /* Enumerate all the USB devices on the system, returning them in a list * of discovered devices. @@ -1110,6 +1131,11 @@ struct usbi_os_backend { clockid_t (*get_timerfd_clockid)(void); #endif + /* Number of bytes to reserve for per-context private backend data. + * This private data area is accessible through the "os_priv" field of + * struct libusb_context. */ + size_t context_priv_size; + /* Number of bytes to reserve for per-device private backend data. * This private data area is accessible through the "os_priv" field of * struct libusb_device. */ @@ -1127,17 +1153,7 @@ struct usbi_os_backend { size_t transfer_priv_size; }; -extern const struct usbi_os_backend * const usbi_backend; - -extern const struct usbi_os_backend linux_usbfs_backend; -extern const struct usbi_os_backend darwin_backend; -extern const struct usbi_os_backend openbsd_backend; -extern const struct usbi_os_backend netbsd_backend; -extern const struct usbi_os_backend windows_backend; -extern const struct usbi_os_backend usbdk_backend; -extern const struct usbi_os_backend wince_backend; -extern const struct usbi_os_backend haiku_usb_raw_backend; -extern const struct usbi_os_backend sunos_backend; +extern const struct usbi_os_backend usbi_backend; extern struct list_head active_contexts_list; extern usbi_mutex_static_t active_contexts_lock; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c similarity index 96% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c index b0219d1b0..35ea1c321 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode:nil -*- */ /* * darwin backend for libusb 1.0 - * Copyright © 2008-2016 Nathan Hjelm + * Copyright © 2008-2017 Nathan Hjelm * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,6 +36,10 @@ #include #include +/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector + * function. Its use is also conditionalized to only older deployment targets. */ +#define OBJC_SILENCE_GC_DEPRECATIONS 1 + #include #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 #include @@ -55,6 +59,14 @@ _Atomic int32_t initCount = ATOMIC_VAR_INIT(0); #define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y) static volatile int32_t initCount = 0; + +#endif + +/* On 10.12 and later, use newly available clock_*() functions */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 +#define OSX_USE_CLOCK_GETTIME 1 +#else +#define OSX_USE_CLOCK_GETTIME 0 #endif #include "darwin_usb.h" @@ -65,15 +77,17 @@ static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT; +#if !OSX_USE_CLOCK_GETTIME static clock_serv_t clock_realtime; static clock_serv_t clock_monotonic; +#endif static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; -static char *darwin_device_class = kIOUSBDeviceClassName; +static const char *darwin_device_class = kIOUSBDeviceClassName; #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) @@ -219,20 +233,21 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (propertyMatchDict) { - /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this - internally (CFNumberType of locationID is 3) */ - CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); + /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this + internally (CFNumberType of locationID is kCFNumberSInt32Type) */ + CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); + if (propertyMatchDict && locationCF) { CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); - /* release our reference to the CFNumber (CFDictionarySetValue retains it) */ - CFRelease (locationCF); - CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); - /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */ - CFRelease (propertyMatchDict); } /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ + + /* release our references as per the Create Rule */ + if (propertyMatchDict) + CFRelease (propertyMatchDict); + if (locationCF) + CFRelease (locationCF); } return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); @@ -300,6 +315,7 @@ static usb_device_t **darwin_device_from_service (io_service_t service) } static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { + UNUSED(ptr); struct libusb_context *ctx; io_service_t service; @@ -308,7 +324,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { while ((service = IOIteratorNext(add_devices))) { /* add this device to each active context's device list */ list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - process_new_device (ctx, service);; + process_new_device (ctx, service); } IOObjectRelease(service); @@ -318,6 +334,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { } static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { + UNUSED(ptr); struct libusb_device *dev = NULL; struct libusb_context *ctx; struct darwin_cached_device *old_device; @@ -516,7 +533,6 @@ static void darwin_check_version (void) { } static int darwin_init(struct libusb_context *ctx) { - host_name_port_t host_self; int rc; rc = pthread_once (&darwin_init_once, darwin_check_version); @@ -530,12 +546,15 @@ static int darwin_init(struct libusb_context *ctx) { } if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) { - /* create the clocks that will be used */ +#if !OSX_USE_CLOCK_GETTIME + /* create the clocks that will be used if clock_gettime() is not available */ + host_name_port_t host_self; host_self = mach_host_self(); host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); mach_port_deallocate(mach_task_self(), host_self); +#endif pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); @@ -548,10 +567,13 @@ static int darwin_init(struct libusb_context *ctx) { return rc; } -static void darwin_exit (void) { +static void darwin_exit (struct libusb_context *ctx) { + UNUSED(ctx); if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) { +#if !OSX_USE_CLOCK_GETTIME mach_port_deallocate(mach_task_self(), clock_realtime); mach_port_deallocate(mach_task_self(), clock_monotonic); +#endif /* stop the event runloop and wait for the thread to terminate. */ CFRunLoopSourceSignal(libusb_darwin_acfls); @@ -866,14 +888,29 @@ static int get_device_port (io_service_t service, UInt8 *port) { return ret; } +static int get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) { + kern_return_t result; + io_service_t parent; + + /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */ + parent = service; + while((result = IORegistryEntryGetParentEntry (parent, kIOServicePlane, &parent)) == kIOReturnSuccess) { + if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) { + /* Success */ + return 1; + } + } + + /* We ran out of parents */ + return 0; +} + static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, struct darwin_cached_device **cached_out) { struct darwin_cached_device *new_device; UInt64 sessionID = 0, parent_sessionID = 0; int ret = LIBUSB_SUCCESS; usb_device_t **device; - io_service_t parent; - kern_return_t result; UInt8 port = 0; /* get some info from the io registry */ @@ -884,11 +921,8 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); - result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent); - - if (kIOReturnSuccess == result) { - (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID); - IOObjectRelease(parent); + if (get_device_parent_sessionID(service, &parent_sessionID)) { + usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID); } usbi_mutex_lock(&darwin_cached_devices_lock); @@ -1005,8 +1039,11 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service) case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; -#if DeviceVersion >= 500 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 + case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; #endif default: usbi_warn (ctx, "Got unknown device speed %d", devSpeed); @@ -1216,9 +1253,9 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { kern_return_t kresult; - u_int8_t numep, direction, number; - u_int8_t dont_care1, dont_care3; - u_int16_t dont_care2; + UInt8 numep, direction, number; + UInt8 dont_care1, dont_care3; + UInt16 dont_care2; int rc; usbi_dbg ("building table of endpoints."); @@ -1965,6 +2002,7 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { } static int darwin_clock_gettime(int clk_id, struct timespec *tp) { +#if !OSX_USE_CLOCK_GETTIME mach_timespec_t sys_time; clock_serv_t clock_ref; @@ -1987,6 +2025,16 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) { tp->tv_nsec = sys_time.tv_nsec; return 0; +#else + switch (clk_id) { + case USBI_CLOCK_MONOTONIC: + return clock_gettime(CLOCK_MONOTONIC, tp); + case USBI_CLOCK_REALTIME: + return clock_gettime(CLOCK_REALTIME, tp); + default: + return LIBUSB_ERROR_INVALID_PARAM; + } +#endif } #if InterfaceVersion >= 550 @@ -2047,7 +2095,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne } #endif -const struct usbi_os_backend darwin_backend = { +const struct usbi_os_backend usbi_backend = { .name = "Darwin", .caps = 0, .init = darwin_init, diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h similarity index 60% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h index 118043421..474567f6a 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h @@ -28,37 +28,58 @@ #include /* IOUSBInterfaceInferface */ -#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +/* New in OS 10.12.0. */ +#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + +#define usb_interface_t IOUSBInterfaceInterface800 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800 +#define InterfaceVersion 800 + +/* New in OS 10.10.0. */ +#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) #define usb_interface_t IOUSBInterfaceInterface700 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 #define InterfaceVersion 700 -#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 +/* New in OS 10.9.0. */ +#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_interface_t IOUSBInterfaceInterface650 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650 +#define InterfaceVersion 650 + +/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) #define usb_interface_t IOUSBInterfaceInterface550 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 #define InterfaceVersion 550 -#elif defined (kIOUSBInterfaceInterfaceID500) +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) #define usb_interface_t IOUSBInterfaceInterface500 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 #define InterfaceVersion 500 -#elif defined (kIOUSBInterfaceInterfaceID300) +/* New in OS 10.5.0. */ +#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_interface_t IOUSBInterfaceInterface300 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 #define InterfaceVersion 300 -#elif defined (kIOUSBInterfaceInterfaceID245) +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_interface_t IOUSBInterfaceInterface245 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 #define InterfaceVersion 245 -#elif defined (kIOUSBInterfaceInterfaceID220) +/* New in OS 10.4.0. */ +#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040) #define usb_interface_t IOUSBInterfaceInterface220 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 @@ -66,43 +87,57 @@ #else -#error "IOUSBFamily is too old. Please upgrade your OS" +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" #endif /* IOUSBDeviceInterface */ -#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +/* New in OS 10.9.0. */ +#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + +#define usb_device_t IOUSBDeviceInterface650 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID650 +#define DeviceVersion 650 + +/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) #define usb_device_t IOUSBDeviceInterface500 #define DeviceInterfaceID kIOUSBDeviceInterfaceID500 #define DeviceVersion 500 -#elif defined (kIOUSBDeviceInterfaceID320) +/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) #define usb_device_t IOUSBDeviceInterface320 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320 #define DeviceVersion 320 -#elif defined (kIOUSBDeviceInterfaceID300) +/* New in OS 10.5.0. */ +#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_device_t IOUSBDeviceInterface300 #define DeviceInterfaceID kIOUSBDeviceInterfaceID300 #define DeviceVersion 300 -#elif defined (kIOUSBDeviceInterfaceID245) +/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) #define usb_device_t IOUSBDeviceInterface245 #define DeviceInterfaceID kIOUSBDeviceInterfaceID245 #define DeviceVersion 245 -#elif defined (kIOUSBDeviceInterfaceID220) +/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */ +#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) + #define usb_device_t IOUSBDeviceInterface197 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197 #define DeviceVersion 197 #else -#error "IOUSBFamily is too old. Please upgrade your OS" +#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target" #endif diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb_raw.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb_raw.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_netlink.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c similarity index 89% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/linux_netlink.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c index 60cf3ad1b..c1ad1ec51 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_netlink.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c @@ -45,24 +45,33 @@ #define NL_GROUP_KERNEL 1 +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif + static int linux_netlink_socket = -1; static int netlink_control_pipe[2] = { -1, -1 }; static pthread_t libusb_linux_event_thread; static void *linux_netlink_event_thread_main(void *arg); -static int set_fd_cloexec_nb(int fd) +static int set_fd_cloexec_nb(int fd, int socktype) { int flags; #if defined(FD_CLOEXEC) - flags = fcntl(fd, F_GETFD); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); - return -1; - } + /* Make sure the netlink socket file descriptor is marked as CLOEXEC */ + if (!(socktype & SOCK_CLOEXEC)) { + flags = fcntl(fd, F_GETFD); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); + return -1; + } - if (!(flags & FD_CLOEXEC)) { if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); return -1; @@ -70,13 +79,14 @@ static int set_fd_cloexec_nb(int fd) } #endif - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); - return -1; - } + /* Make sure the netlink socket is non-blocking */ + if (!(socktype & SOCK_NONBLOCK)) { + flags = fcntl(fd, F_GETFL); + if (flags == -1) { + usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); + return -1; + } - if (!(flags & O_NONBLOCK)) { if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); return -1; @@ -89,21 +99,15 @@ static int set_fd_cloexec_nb(int fd) int linux_netlink_start_event_monitor(void) { struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; - int socktype = SOCK_RAW; + int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC; int opt = 1; int ret; -#if defined(SOCK_CLOEXEC) - socktype |= SOCK_CLOEXEC; -#endif -#if defined(SOCK_NONBLOCK) - socktype |= SOCK_NONBLOCK; -#endif - linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); if (linux_netlink_socket == -1 && errno == EINVAL) { usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); - linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + socktype = SOCK_RAW; + linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); } if (linux_netlink_socket == -1) { @@ -111,7 +115,7 @@ int linux_netlink_start_event_monitor(void) goto err; } - ret = set_fd_cloexec_nb(linux_netlink_socket); + ret = set_fd_cloexec_nb(linux_netlink_socket, socktype); if (ret == -1) goto err_close_socket; @@ -162,7 +166,7 @@ int linux_netlink_stop_event_monitor(void) /* Write some dummy data to the control pipe and * wait for the thread to exit */ - r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy)); + r = write(netlink_control_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) usbi_warn(NULL, "netlink control pipe signal failed"); @@ -356,7 +360,8 @@ static int linux_netlink_read_message(void) static void *linux_netlink_event_thread_main(void *arg) { char dummy; - ssize_t r; + int r; + ssize_t nb; struct pollfd fds[] = { { .fd = netlink_control_pipe[0], .events = POLLIN }, @@ -368,11 +373,15 @@ static void *linux_netlink_event_thread_main(void *arg) usbi_dbg("netlink event thread entering"); - while (poll(fds, 2, -1) >= 0) { + while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { + if (r < 0) { + /* temporary failure */ + continue; + } if (fds[0].revents & POLLIN) { /* activity on control pipe, read the byte and exit */ - r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) + nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) usbi_warn(NULL, "netlink control pipe read failed"); break; } diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_udev.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c similarity index 90% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/linux_udev.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c index 61d953d8c..c97806ba6 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_udev.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c @@ -82,17 +82,33 @@ int linux_udev_start_event_monitor(void) udev_monitor_fd = udev_monitor_get_fd(udev_monitor); +#if defined(FD_CLOEXEC) + /* Make sure the udev file descriptor is marked as CLOEXEC */ + r = fcntl(udev_monitor_fd, F_GETFD); + if (r == -1) { + usbi_err(NULL, "geting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + if (!(r & FD_CLOEXEC)) { + if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) { + usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); + goto err_free_monitor; + } + } +#endif + /* Some older versions of udev are not non-blocking by default, * so make sure this is set */ r = fcntl(udev_monitor_fd, F_GETFL); if (r == -1) { - usbi_err(NULL, "getting udev monitor fd flags (%d)", errno); + usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno); goto err_free_monitor; } - r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK); - if (r) { - usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); - goto err_free_monitor; + if (!(r & O_NONBLOCK)) { + if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) { + usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno); + goto err_free_monitor; + } } r = usbi_pipe(udev_control_pipe); @@ -134,7 +150,7 @@ int linux_udev_stop_event_monitor(void) /* Write some dummy data to the control pipe and * wait for the thread to exit */ - r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy)); + r = write(udev_control_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(NULL, "udev control pipe signal failed"); } @@ -162,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg) { char dummy; int r; + ssize_t nb; struct udev_device* udev_dev; struct pollfd fds[] = { {.fd = udev_control_pipe[0], @@ -179,8 +196,8 @@ static void *linux_udev_event_thread_main(void *arg) } if (fds[0].revents & POLLIN) { /* activity on control pipe, read the byte and exit */ - r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) { + nb = read(udev_control_pipe[0], &dummy, sizeof(dummy)); + if (nb <= 0) { usbi_warn(NULL, "udev control pipe read failed"); } break; @@ -274,6 +291,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx) udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); + entry = NULL; udev_list_entry_foreach(entry, devices) { const char *path = udev_list_entry_get_name(entry); uint8_t busnum = 0, devaddr = 0; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c similarity index 93% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c index 6b89ba288..768e7d5a6 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c @@ -81,6 +81,19 @@ static const char *usbfs_path = NULL; /* use usbdev*.* device names in /dev instead of the usbfs bus directories */ static int usbdev_names = 0; +/* Linux has changed the maximum length of an individual isochronous packet + * over time. Initially this limit was 1,023 bytes, but Linux 2.6.18 + * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to + * 8,192 bytes to support higher bandwidth devices. Linux 3.10 + * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this + * value to 49,152 bytes to support super speed devices. + */ +static unsigned int max_iso_packet_len = 0; + +/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the + * close-on-exec flag in the underlying file descriptor. */ +static int supports_flag_cloexec = -1; + /* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically * allows us to mark URBs as being part of a specific logical transfer when * we submit them to the kernel. then, on any error except a cancellation, all @@ -136,6 +149,12 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int); static int linux_default_scan_devices (struct libusb_context *ctx); #endif +struct kernel_version { + int major; + int minor; + int sublevel; +}; + struct linux_device_priv { char *sysfs_dir; unsigned char *descriptors; @@ -180,6 +199,16 @@ struct linux_transfer_priv { int iso_packet_offset; }; +static int _open(const char *path, int flags) +{ +#if defined(O_CLOEXEC) + if (supports_flag_cloexec) + return open(path, flags | O_CLOEXEC); + else +#endif + return open(path, flags); +} + static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) { struct libusb_context *ctx = DEVICE_CTX(dev); @@ -194,7 +223,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) snprintf(path, PATH_MAX, "%s/%03d/%03d", usbfs_path, dev->bus_number, dev->device_address); - fd = open(path, mode); + fd = _open(path, mode); if (fd != -1) return fd; /* Success */ @@ -205,7 +234,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) /* Wait 10ms for USB device path creation.*/ nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - fd = open(path, mode); + fd = _open(path, mode); if (fd != -1) return fd; /* Success */ } @@ -342,39 +371,59 @@ static clockid_t find_monotonic_clock(void) return CLOCK_REALTIME; } -static int kernel_version_ge(int major, int minor, int sublevel) +static int get_kernel_version(struct libusb_context *ctx, + struct kernel_version *ver) { struct utsname uts; - int atoms, kmajor, kminor, ksublevel; + int atoms; - if (uname(&uts) < 0) - return -1; - atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel); - if (atoms < 1) + if (uname(&uts) < 0) { + usbi_err(ctx, "uname failed, errno %d", errno); return -1; + } - if (kmajor > major) + atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel); + if (atoms < 1) { + usbi_err(ctx, "failed to parse uname release '%s'", uts.release); + return -1; + } + + if (atoms < 2) + ver->minor = -1; + if (atoms < 3) + ver->sublevel = -1; + + usbi_dbg("reported kernel version is %s", uts.release); + + return 0; +} + +static int kernel_version_ge(const struct kernel_version *ver, + int major, int minor, int sublevel) +{ + if (ver->major > major) return 1; - if (kmajor < major) + else if (ver->major < major) return 0; /* kmajor == major */ - if (atoms < 2) + if (ver->minor == -1 && ver->sublevel == -1) return 0 == minor && 0 == sublevel; - if (kminor > minor) + else if (ver->minor > minor) return 1; - if (kminor < minor) + else if (ver->minor < minor) return 0; /* kminor == minor */ - if (atoms < 3) + if (ver->sublevel == -1) return 0 == sublevel; - return ksublevel >= sublevel; + return ver->sublevel >= sublevel; } static int op_init(struct libusb_context *ctx) { + struct kernel_version kversion; struct stat statbuf; int r; @@ -387,13 +436,17 @@ static int op_init(struct libusb_context *ctx) if (monotonic_clkid == -1) monotonic_clkid = find_monotonic_clock(); + if (get_kernel_version(ctx, &kversion) < 0) + return LIBUSB_ERROR_OTHER; + + if (supports_flag_cloexec == -1) { + /* O_CLOEXEC flag available from Linux 2.6.23 */ + supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23); + } + if (supports_flag_bulk_continuation == -1) { /* bulk continuation URB flag available from Linux 2.6.32 */ - supports_flag_bulk_continuation = kernel_version_ge(2,6,32); - if (supports_flag_bulk_continuation == -1) { - usbi_err(ctx, "error checking for bulk continuation support"); - return LIBUSB_ERROR_OTHER; - } + supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32); } if (supports_flag_bulk_continuation) @@ -401,32 +454,31 @@ static int op_init(struct libusb_context *ctx) if (-1 == supports_flag_zero_packet) { /* zero length packet URB flag fixed since Linux 2.6.31 */ - supports_flag_zero_packet = kernel_version_ge(2,6,31); - if (-1 == supports_flag_zero_packet) { - usbi_err(ctx, "error checking for zero length packet support"); - return LIBUSB_ERROR_OTHER; - } + supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31); } if (supports_flag_zero_packet) usbi_dbg("zero length packet flag supported"); + if (!max_iso_packet_len) { + if (kernel_version_ge(&kversion,3,10,0)) + max_iso_packet_len = 49152; + else if (kernel_version_ge(&kversion,2,6,18)) + max_iso_packet_len = 8192; + else + max_iso_packet_len = 1023; + } + + usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len); + if (-1 == sysfs_has_descriptors) { /* sysfs descriptors has all descriptors since Linux 2.6.26 */ - sysfs_has_descriptors = kernel_version_ge(2,6,26); - if (-1 == sysfs_has_descriptors) { - usbi_err(ctx, "error checking for sysfs descriptors"); - return LIBUSB_ERROR_OTHER; - } + sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26); } if (-1 == sysfs_can_relate_devices) { /* sysfs has busnum since Linux 2.6.22 */ - sysfs_can_relate_devices = kernel_version_ge(2,6,22); - if (-1 == sysfs_can_relate_devices) { - usbi_err(ctx, "error checking for sysfs busnum"); - return LIBUSB_ERROR_OTHER; - } + sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22); } if (sysfs_can_relate_devices || sysfs_has_descriptors) { @@ -463,8 +515,9 @@ static int op_init(struct libusb_context *ctx) return r; } -static void op_exit(void) +static void op_exit(struct libusb_context *ctx) { + UNUSED(ctx); usbi_mutex_static_lock(&linux_hotplug_startstop_lock); assert(init_count != 0); if (!--init_count) { @@ -526,7 +579,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr) snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); - fd = open(filename, O_RDONLY); + fd = _open(filename, O_RDONLY); if (fd < 0) { usbi_err(DEVICE_CTX(dev), "open %s failed ret=%d errno=%d", filename, fd, errno); @@ -542,12 +595,12 @@ static int __read_sysfs_attr(struct libusb_context *ctx, { char filename[PATH_MAX]; FILE *f; - int r, value; + int fd, r, value; snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, devname, attr); - f = fopen(filename, "r"); - if (f == NULL) { + fd = _open(filename, O_RDONLY); + if (fd == -1) { if (errno == ENOENT) { /* File doesn't exist. Assume the device has been disconnected (see trac ticket #70). */ @@ -557,6 +610,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx, return LIBUSB_ERROR_IO; } + f = fdopen(fd, "r"); + if (f == NULL) { + usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno); + close(fd); + return LIBUSB_ERROR_OTHER; + } + r = fscanf(f, "%d", &value); fclose(f); if (r != 1) { @@ -806,7 +866,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev, if (r < 0) return r; - len = MIN(len, r); + len = MIN(len, (size_t)r); memcpy(buffer, config_desc, len); return len; } @@ -836,7 +896,7 @@ static int op_get_config_descriptor(struct libusb_device *dev, descriptors += r; } - len = MIN(len, r); + len = MIN(len, (size_t)r); memcpy(buffer, descriptors, len); return len; } @@ -911,6 +971,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, case 12: dev->speed = LIBUSB_SPEED_FULL; break; case 480: dev->speed = LIBUSB_SPEED_HIGH; break; case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; + case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break; default: usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); } @@ -1239,11 +1300,12 @@ static int sysfs_get_device_list(struct libusb_context *ctx) { DIR *devices = opendir(SYSFS_DEVICE_PATH); struct dirent *entry; - int r = LIBUSB_ERROR_IO; + int num_devices = 0; + int num_enumerated = 0; if (!devices) { usbi_err(ctx, "opendir devices failed errno=%d", errno); - return r; + return LIBUSB_ERROR_IO; } while ((entry = readdir(devices))) { @@ -1251,16 +1313,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx) || strchr(entry->d_name, ':')) continue; + num_devices++; + if (sysfs_scan_device(ctx, entry->d_name)) { usbi_dbg("failed to enumerate dir entry %s", entry->d_name); continue; } - r = 0; + num_enumerated++; } closedir(devices); - return r; + + /* successful if at least one device was enumerated or no devices were found */ + if (num_enumerated || !num_devices) + return LIBUSB_SUCCESS; + else + return LIBUSB_ERROR_IO; } static int linux_default_scan_devices (struct libusb_context *ctx) @@ -1685,10 +1754,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, strcpy(dc.driver, "usbfs"); dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); - if (r == 0 || (r != 0 && errno != ENOTTY)) { - if (r == 0) - return 0; - + if (r != 0 && errno != ENOTTY) { switch (errno) { case EBUSY: return LIBUSB_ERROR_BUSY; @@ -1700,7 +1766,8 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, usbi_err(HANDLE_CTX(handle), "disconnect-and-claim failed errno %d", errno); return LIBUSB_ERROR_OTHER; - } + } else if (r == 0) + return 0; /* Fallback code for kernels which don't support the disconnect-and-claim ioctl */ @@ -1973,38 +2040,43 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) struct linux_device_handle_priv *dpriv = _device_handle_priv(transfer->dev_handle); struct usbfs_urb **urbs; - size_t alloc_size; int num_packets = transfer->num_iso_packets; - int i; - int this_urb_len = 0; - int num_urbs = 1; - int packet_offset = 0; + int num_packets_remaining; + int i, j; + int num_urbs; unsigned int packet_len; + unsigned int total_len = 0; unsigned char *urb_buffer = transfer->buffer; - /* usbfs places arbitrary limits on iso URBs. this limit has changed - * at least three times, and it's difficult to accurately detect which - * limit this running kernel might impose. so we attempt to submit - * whatever the user has provided. if the kernel rejects the request - * due to its size, we return an error indicating such to the user. - */ + if (num_packets < 1) + return LIBUSB_ERROR_INVALID_PARAM; - /* calculate how many URBs we need */ + /* usbfs places arbitrary limits on iso URBs. this limit has changed + * at least three times, but we attempt to detect this limit during + * init and check it here. if the kernel rejects the request due to + * its size, we return an error indicating such to the user. + */ for (i = 0; i < num_packets; i++) { - unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len; packet_len = transfer->iso_packet_desc[i].length; - if (packet_len > space_remaining) { - num_urbs++; - this_urb_len = packet_len; - /* check that we can actually support this packet length */ - if (this_urb_len > MAX_ISO_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - } else { - this_urb_len += packet_len; + if (packet_len > max_iso_packet_len) { + usbi_warn(TRANSFER_CTX(transfer), + "iso packet length of %u bytes exceeds maximum of %u bytes", + packet_len, max_iso_packet_len); + return LIBUSB_ERROR_INVALID_PARAM; } + + total_len += packet_len; } - usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024); + + if (transfer->length < (int)total_len) + return LIBUSB_ERROR_INVALID_PARAM; + + /* usbfs limits the number of iso packets per URB */ + num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB; + + usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, + transfer->length); urbs = calloc(num_urbs, sizeof(*urbs)); if (!urbs) @@ -2017,31 +2089,15 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) tpriv->iso_packet_offset = 0; /* allocate + initialize each URB with the correct number of packets */ - for (i = 0; i < num_urbs; i++) { + num_packets_remaining = num_packets; + for (i = 0, j = 0; i < num_urbs; i++) { + int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB); struct usbfs_urb *urb; - unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH; - int urb_packet_offset = 0; - unsigned char *urb_buffer_orig = urb_buffer; - int j; + size_t alloc_size; int k; - /* swallow up all the packets we can fit into this URB */ - while (packet_offset < transfer->num_iso_packets) { - packet_len = transfer->iso_packet_desc[packet_offset].length; - if (packet_len <= space_remaining_in_urb) { - /* throw it in */ - urb_packet_offset++; - packet_offset++; - space_remaining_in_urb -= packet_len; - urb_buffer += packet_len; - } else { - /* it can't fit, save it for the next URB */ - break; - } - } - alloc_size = sizeof(*urb) - + (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc)); + + (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc)); urb = calloc(1, alloc_size); if (!urb) { free_iso_urbs(tpriv); @@ -2050,10 +2106,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) urbs[i] = urb; /* populate packet lengths */ - for (j = 0, k = packet_offset - urb_packet_offset; - k < packet_offset; k++, j++) { - packet_len = transfer->iso_packet_desc[k].length; - urb->iso_frame_desc[j].length = packet_len; + for (k = 0; k < num_packets_in_urb; j++, k++) { + packet_len = transfer->iso_packet_desc[j].length; + urb->buffer_length += packet_len; + urb->iso_frame_desc[k].length = packet_len; } urb->usercontext = itransfer; @@ -2061,8 +2117,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) /* FIXME: interface for non-ASAP data? */ urb->flags = USBFS_URB_ISO_ASAP; urb->endpoint = transfer->endpoint; - urb->number_of_packets = urb_packet_offset; - urb->buffer = urb_buffer_orig; + urb->number_of_packets = num_packets_in_urb; + urb->buffer = urb_buffer; + + urb_buffer += urb->buffer_length; + num_packets_remaining -= num_packets_in_urb; } /* submit URBs */ @@ -2075,6 +2134,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, transfer too large"); r = LIBUSB_ERROR_INVALID_PARAM; + } else if (errno == EMSGSIZE) { + usbi_warn(TRANSFER_CTX(transfer), + "submiturb failed, iso packet length too large"); + r = LIBUSB_ERROR_INVALID_PARAM; } else { usbi_err(TRANSFER_CTX(transfer), "submiturb failed error %d errno=%d", r, errno); @@ -2213,7 +2276,6 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer) USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - /* urbs can be freed also in submit_transfer so lock mutex first */ switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_BULK: @@ -2685,7 +2747,7 @@ static clockid_t op_get_timerfd_clockid(void) } #endif -const struct usbi_os_backend linux_usbfs_backend = { +const struct usbi_os_backend usbi_backend = { .name = "Linux usbfs", .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, .init = op_init, diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h similarity index 99% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h index 8bd3ebcb1..24496325f 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h @@ -81,10 +81,11 @@ struct usbfs_iso_packet_desc { unsigned int status; }; -#define MAX_ISO_BUFFER_LENGTH 49152 * 128 #define MAX_BULK_BUFFER_LENGTH 16384 #define MAX_CTRL_BUFFER_LENGTH 4096 +#define MAX_ISO_PACKETS_PER_URB 128 + struct usbfs_urb { unsigned char type; unsigned char endpoint; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/netbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c similarity index 98% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/netbsd_usb.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c index ad1ede73e..d9c059a77 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/netbsd_usb.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c @@ -86,11 +86,12 @@ static int _sync_control_transfer(struct usbi_transfer *); static int _sync_gen_transfer(struct usbi_transfer *); static int _access_endpoint(struct libusb_transfer *); -const struct usbi_os_backend netbsd_backend = { +const struct usbi_os_backend usbi_backend = { "Synchronous NetBSD backend", 0, NULL, /* init() */ NULL, /* exit() */ + NULL, /* set_option() */ netbsd_get_device_list, NULL, /* hotplug_poll */ netbsd_open, @@ -131,6 +132,7 @@ const struct usbi_os_backend netbsd_backend = { netbsd_handle_transfer_completion, netbsd_clock_gettime, + 0, /* context_priv_size */ sizeof(struct device_priv), sizeof(struct handle_priv), 0, /* transfer_priv_size */ @@ -212,7 +214,6 @@ error: int netbsd_open(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; dpriv->fd = open(dpriv->devnode, O_RDWR); @@ -230,7 +231,6 @@ netbsd_open(struct libusb_device_handle *handle) void netbsd_close(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; usbi_dbg("close: fd %d", dpriv->fd); diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/openbsd_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c similarity index 99% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/openbsd_usb.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c index c66025711..f174e496c 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/openbsd_usb.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c @@ -89,11 +89,12 @@ static int _access_endpoint(struct libusb_transfer *); static int _bus_open(int); -const struct usbi_os_backend openbsd_backend = { +const struct usbi_os_backend usbi_backend = { "Synchronous OpenBSD backend", 0, NULL, /* init() */ NULL, /* exit() */ + NULL, /* set_option() */ obsd_get_device_list, NULL, /* hotplug_poll */ obsd_open, @@ -134,6 +135,7 @@ const struct usbi_os_backend openbsd_backend = { obsd_handle_transfer_completion, obsd_clock_gettime, + 0, /* context_priv_size */ sizeof(struct device_priv), sizeof(struct handle_priv), 0, /* transfer_priv_size */ @@ -246,7 +248,6 @@ obsd_get_device_list(struct libusb_context * ctx, int obsd_open(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; char devnode[16]; @@ -270,7 +271,6 @@ obsd_open(struct libusb_device_handle *handle) void obsd_close(struct libusb_device_handle *handle) { - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; if (dpriv->devname) { diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c similarity index 56% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c index e2f55a57a..337714aa6 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c @@ -29,25 +29,56 @@ int usbi_pipe(int pipefd[2]) { +#if defined(HAVE_PIPE2) + int ret = pipe2(pipefd, O_CLOEXEC); +#else int ret = pipe(pipefd); +#endif + if (ret != 0) { + usbi_err(NULL, "failed to create pipe (%d)", errno); return ret; } + +#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC) + ret = fcntl(pipefd[0], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } + + ret = fcntl(pipefd[1], F_GETFD); + if (ret == -1) { + usbi_err(NULL, "failed to get pipe fd flags (%d)", errno); + goto err_close_pipe; + } + ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd flags (%d)", errno); + goto err_close_pipe; + } +#endif + ret = fcntl(pipefd[1], F_GETFL); if (ret == -1) { - usbi_dbg("Failed to get pipe fd flags: %d", errno); + usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno); goto err_close_pipe; } ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); - if (ret != 0) { - usbi_dbg("Failed to set non-blocking on new pipe: %d", errno); + if (ret == -1) { + usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno); goto err_close_pipe; } return 0; err_close_pipe: - usbi_close(pipefd[0]); - usbi_close(pipefd[1]); + close(pipefd[0]); + close(pipefd[1]); return ret; } diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c new file mode 100644 index 000000000..4d283333d --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c @@ -0,0 +1,364 @@ +/* + * poll_windows: poll compatibility wrapper for Windows + * Copyright © 2017 Chris Dickens + * + * This 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 2.1 of the License, or (at your option) any later version. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* + * poll() and pipe() Windows compatibility layer for libusb 1.0 + * + * The way this layer works is by using OVERLAPPED with async I/O transfers, as + * OVERLAPPED have an associated event which is flagged for I/O completion. + * + * For USB pollable async I/O, you would typically: + * - obtain a Windows HANDLE to a file or device that has been opened in + * OVERLAPPED mode + * - call usbi_create_fd with this handle to obtain a custom fd. + * - leave the core functions call the poll routine and flag POLLIN/POLLOUT + * + * The pipe pollable synchronous I/O works using the overlapped event associated + * with a fake pipe. The read/write functions are only meant to be used in that + * context. + */ +#include + +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" + +// public fd data +const struct winfd INVALID_WINFD = { -1, NULL }; + +// private data +struct file_descriptor { + enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type; + OVERLAPPED overlapped; +}; + +static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER; +static struct file_descriptor *fd_table[MAX_FDS]; + +static struct file_descriptor *create_fd(enum fd_type type) +{ + struct file_descriptor *fd = calloc(1, sizeof(*fd)); + if (fd == NULL) + return NULL; + fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (fd->overlapped.hEvent == NULL) { + free(fd); + return NULL; + } + fd->type = type; + return fd; +} + +static void free_fd(struct file_descriptor *fd) +{ + CloseHandle(fd->overlapped.hEvent); + free(fd); +} + +/* + * Create both an fd and an OVERLAPPED, so that it can be used with our + * polling function + * The handle MUST support overlapped transfers (usually requires CreateFile + * with FILE_FLAG_OVERLAPPED) + * Return a pollable file descriptor struct, or INVALID_WINFD on error + * + * Note that the fd returned by this function is a per-transfer fd, rather + * than a per-session fd and cannot be used for anything else but our + * custom functions. + * if you plan to do R/W on the same handle, you MUST create 2 fds: one for + * read and one for write. Using a single R/W fd is unsupported and will + * produce unexpected results + */ +struct winfd usbi_create_fd(void) +{ + struct file_descriptor *fd; + struct winfd wfd; + + fd = create_fd(FD_TYPE_TRANSFER); + if (fd == NULL) + return INVALID_WINFD; + + usbi_mutex_static_lock(&fd_table_lock); + for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) { + if (fd_table[wfd.fd] != NULL) + continue; + fd_table[wfd.fd] = fd; + break; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (wfd.fd == MAX_FDS) { + free_fd(fd); + return INVALID_WINFD; + } + + wfd.overlapped = &fd->overlapped; + + return wfd; +} + +static int check_pollfds(struct pollfd *fds, unsigned int nfds, + HANDLE *wait_handles, DWORD *nb_wait_handles) +{ + struct file_descriptor *fd; + unsigned int n; + int nready = 0; + + usbi_mutex_static_lock(&fd_table_lock); + + for (n = 0; n < nfds; ++n) { + fds[n].revents = 0; + + // Keep it simple - only allow either POLLIN *or* POLLOUT + assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT)); + if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS)) + fd = fd_table[fds[n].fd]; + else + fd = NULL; + + assert(fd != NULL); + if (fd == NULL) { + fds[n].revents = POLLNVAL; + nready++; + continue; + } + + if (HasOverlappedIoCompleted(&fd->overlapped) + && (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) { + fds[n].revents = fds[n].events; + nready++; + } else if (wait_handles != NULL) { + if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) { + usbi_warn(NULL, "too many HANDLEs to wait on"); + continue; + } + wait_handles[*nb_wait_handles] = fd->overlapped.hEvent; + (*nb_wait_handles)++; + } + } + + usbi_mutex_static_unlock(&fd_table_lock); + + return nready; +} +/* + * POSIX poll equivalent, using Windows OVERLAPPED + * Currently, this function only accepts one of POLLIN or POLLOUT per fd + * (but you can create multiple fds from the same handle for read and write) + */ +int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) +{ + HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; + DWORD nb_wait_handles = 0; + DWORD ret; + int nready; + + nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles); + + // If nothing was triggered, wait on all fds that require it + if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) { + ret = WaitForMultipleObjects(nb_wait_handles, wait_handles, + FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout); + if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) { + nready = check_pollfds(fds, nfds, NULL, NULL); + } else if (ret != WAIT_TIMEOUT) { + if (ret == WAIT_FAILED) + usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError()); + nready = -1; + } + } + + return nready; +} + +/* + * close a fake file descriptor + */ +int usbi_close(int _fd) +{ + struct file_descriptor *fd; + + if (_fd < 0 || _fd >= MAX_FDS) + goto err_badfd; + + usbi_mutex_static_lock(&fd_table_lock); + fd = fd_table[_fd]; + fd_table[_fd] = NULL; + usbi_mutex_static_unlock(&fd_table_lock); + + if (fd == NULL) + goto err_badfd; + + if (fd->type == FD_TYPE_PIPE) { + // InternalHigh is our reference count + fd->overlapped.InternalHigh--; + if (fd->overlapped.InternalHigh == 0) + free_fd(fd); + } else { + free_fd(fd); + } + + return 0; + +err_badfd: + errno = EBADF; + return -1; +} + +/* +* Create a fake pipe. +* As libusb only uses pipes for signaling, all we need from a pipe is an +* event. To that extent, we create a single wfd and overlapped as a means +* to access that event. +*/ +int usbi_pipe(int filedes[2]) +{ + struct file_descriptor *fd; + int r_fd = -1, w_fd = -1; + int i; + + fd = create_fd(FD_TYPE_PIPE); + if (fd == NULL) { + errno = ENOMEM; + return -1; + } + + // Use InternalHigh as a reference count + fd->overlapped.Internal = STATUS_PENDING; + fd->overlapped.InternalHigh = 2; + + usbi_mutex_static_lock(&fd_table_lock); + do { + for (i = 0; i < MAX_FDS; i++) { + if (fd_table[i] != NULL) + continue; + if (r_fd == -1) { + r_fd = i; + } else if (w_fd == -1) { + w_fd = i; + break; + } + } + + if (i == MAX_FDS) + break; + + fd_table[r_fd] = fd; + fd_table[w_fd] = fd; + + } while (0); + usbi_mutex_static_unlock(&fd_table_lock); + + if (i == MAX_FDS) { + free_fd(fd); + errno = EMFILE; + return -1; + } + + filedes[0] = r_fd; + filedes[1] = w_fd; + + return 0; +} + +/* + * synchronous write for fake "pipe" signaling + */ +ssize_t usbi_write(int fd, const void *buf, size_t count) +{ + int error = EBADF; + + UNUSED(buf); + + if (fd < 0 || fd >= MAX_FDS) + goto err_out; + + if (count != sizeof(unsigned char)) { + usbi_err(NULL, "this function should only used for signaling"); + error = EINVAL; + goto err_out; + } + + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_WAIT_0; + SetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (error) + goto err_out; + + return sizeof(unsigned char); + +err_out: + errno = error; + return -1; +} + +/* + * synchronous read for fake "pipe" signaling + */ +ssize_t usbi_read(int fd, void *buf, size_t count) +{ + int error = EBADF; + + UNUSED(buf); + + if (fd < 0 || fd >= MAX_FDS) + goto err_out; + + if (count != sizeof(unsigned char)) { + usbi_err(NULL, "this function should only used for signaling"); + error = EINVAL; + goto err_out; + } + + usbi_mutex_static_lock(&fd_table_lock); + if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) { + assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0); + assert(fd_table[fd]->overlapped.InternalHigh == 2); + fd_table[fd]->overlapped.Internal = STATUS_PENDING; + ResetEvent(fd_table[fd]->overlapped.hEvent); + error = 0; + } + usbi_mutex_static_unlock(&fd_table_lock); + + if (error) + goto err_out; + + return sizeof(unsigned char); + +err_out: + errno = error; + return -1; +} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h similarity index 70% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h index aa4c985da..bd22c7f62 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h @@ -2,6 +2,7 @@ * Windows compat: POSIX compatibility wrapper * Copyright © 2012-2013 RealVNC Ltd. * Copyright © 2009-2010 Pete Batard + * Copyright © 2016-2018 Chris Dickens * With contributions from Michael Plante, Orin Eman et al. * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. * @@ -40,21 +41,6 @@ #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) -/* Windows versions */ -enum windows_version { - WINDOWS_CE = -2, - WINDOWS_UNDEFINED = -1, - WINDOWS_UNSUPPORTED = 0, - WINDOWS_XP = 0x51, - WINDOWS_2003 = 0x52, // Also XP x64 - WINDOWS_VISTA = 0x60, - WINDOWS_7 = 0x61, - WINDOWS_8 = 0x62, - WINDOWS_8_1_OR_LATER = 0x63, - WINDOWS_MAX -}; -extern int windows_version; - #define MAX_FDS 256 #define POLLIN 0x0001 /* There is data to read */ @@ -65,46 +51,26 @@ extern int windows_version; #define POLLNVAL 0x0020 /* Invalid request: fd not open */ struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ }; -// access modes -enum rw_type { - RW_NONE, - RW_READ, - RW_WRITE, -}; - -// fd struct that can be used for polling on Windows -typedef int cancel_transfer(struct usbi_transfer *itransfer); - struct winfd { - int fd; // what's exposed to libusb core - HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it - OVERLAPPED* overlapped; // what will report our I/O status - struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed - cancel_transfer *cancel_fn; // Function pointer to cancel transfer API - enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) + int fd; // what's exposed to libusb core + OVERLAPPED *overlapped; // what will report our I/O status }; + extern const struct winfd INVALID_WINFD; +struct winfd usbi_create_fd(void); + int usbi_pipe(int pipefd[2]); int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); ssize_t usbi_write(int fd, const void *buf, size_t count); ssize_t usbi_read(int fd, void *buf, size_t count); int usbi_close(int fd); -void init_polling(void); -void exit_polling(void); -struct winfd usbi_create_fd(HANDLE handle, int access_mode, - struct usbi_transfer *transfer, cancel_transfer *cancel_fn); -void usbi_free_fd(struct winfd* winfd); -struct winfd fd_to_winfd(int fd); -struct winfd handle_to_winfd(HANDLE handle); -struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); - /* * Timeval operations */ diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c similarity index 71% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c index cb608976b..7150a3e9d 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,21 +29,34 @@ #include #include #include +#include #include #include #include +#include +#include #include +#include #include #include #include "libusbi.h" #include "sunos_usb.h" +#define UPDATEDRV_PATH "/usr/sbin/update_drv" +#define UPDATEDRV "update_drv" + +typedef list_t string_list_t; +typedef struct string_node { + char *string; + list_node_t link; +} string_node_t; + /* * Backend functions */ static int sunos_init(struct libusb_context *); -static void sunos_exit(void); +static void sunos_exit(struct libusb_context *); static int sunos_get_device_list(struct libusb_context *, struct discovered_devs **); static int sunos_open(struct libusb_device_handle *); @@ -67,6 +81,162 @@ static int sunos_cancel_transfer(struct usbi_transfer *); static void sunos_clear_transfer_priv(struct usbi_transfer *); static int sunos_handle_transfer_completion(struct usbi_transfer *); static int sunos_clock_gettime(int, struct timespec *); +static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface); +static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number); +static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv); +static int sunos_usb_ioctl(struct libusb_device *dev, int cmd); + +static struct devctl_iocdata iocdata; +static int sunos_get_link(di_devlink_t devlink, void *arg) +{ + walk_link_t *larg = (walk_link_t *)arg; + const char *p; + const char *q; + + if (larg->path) { + char *content = (char *)di_devlink_content(devlink); + char *start = strstr(content, "/devices/"); + start += strlen("/devices"); + usbi_dbg("%s", start); + + /* line content must have minor node */ + if (start == NULL || + strncmp(start, larg->path, larg->len) != 0 || + start[larg->len] != ':') + return (DI_WALK_CONTINUE); + } + + p = di_devlink_path(devlink); + q = strrchr(p, '/'); + usbi_dbg("%s", q); + + *(larg->linkpp) = strndup(p, strlen(p) - strlen(q)); + + return (DI_WALK_TERMINATE); +} + + +static int sunos_physpath_to_devlink( + const char *node_path, const char *match, char **link_path) +{ + walk_link_t larg; + di_devlink_handle_t hdl; + + *link_path = NULL; + larg.linkpp = link_path; + if ((hdl = di_devlink_init(NULL, 0)) == NULL) { + usbi_dbg("di_devlink_init failure"); + return (-1); + } + + larg.len = strlen(node_path); + larg.path = (char *)node_path; + + (void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK, + (void *)&larg, sunos_get_link); + + (void) di_devlink_fini(&hdl); + + if (*link_path == NULL) { + usbi_dbg("there is no devlink for this path"); + return (-1); + } + + return 0; +} + +static int +sunos_usb_ioctl(struct libusb_device *dev, int cmd) +{ + int fd; + nvlist_t *nvlist; + char *end; + char *phypath; + char *hubpath; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + devctl_ap_state_t devctl_ap_state; + + dpriv = (sunos_dev_priv_t *)dev->os_priv; + phypath = dpriv->phypath; + + end = strrchr(phypath, '/'); + if (end == NULL) + return (-1); + hubpath = strndup(phypath, end - phypath); + if (hubpath == NULL) + return (-1); + + end = strrchr(hubpath, '@'); + if (end == NULL) { + free(hubpath); + return (-1); + } + end++; + usbi_dbg("unitaddr: %s", end); + + nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); + nvlist_add_int32(nvlist, "port", dev->port_number); + //find the hub path + snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath); + usbi_dbg("ioctl hub path: %s", path_arg); + + fd = open(path_arg, O_RDONLY); + if (fd < 0) { + usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno)); + nvlist_free(nvlist); + free(hubpath); + return (-1); + } + + memset(&iocdata, 0, sizeof(iocdata)); + memset(&devctl_ap_state, 0, sizeof(devctl_ap_state)); + + nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0); + + iocdata.cmd = DEVCTL_AP_GETSTATE; + iocdata.flags = 0; + iocdata.c_nodename = "hub"; + iocdata.c_unitaddr = end; + iocdata.cpyout_buf = &devctl_ap_state; + usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz); + + errno = 0; + if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, DEVCTL_AP_GETSTATE, errno, strerror(errno)); + } else { + usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate); + usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate); + } + + errno = 0; + iocdata.cmd = cmd; + if (ioctl(fd, (int)cmd, &iocdata) != 0) { + usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)", + fd, cmd, errno, strerror(errno)); + sleep(2); + } + + close(fd); + free(iocdata.nvl_user); + nvlist_free(nvlist); + free(hubpath); + + return (-errno); +} + +static int +sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface) +{ + sunos_dev_priv_t *dpriv; + dpriv = (sunos_dev_priv_t *)dev->dev->os_priv; + + usbi_dbg("%s", dpriv->ugenpath); + + return (dpriv->ugenpath == NULL); +} /* * Private functions @@ -79,11 +249,229 @@ static int sunos_init(struct libusb_context *ctx) return (LIBUSB_SUCCESS); } -static void sunos_exit(void) +static void sunos_exit(struct libusb_context *ctx) { usbi_dbg(""); } +static string_list_t * +sunos_new_string_list(void) +{ + string_list_t *list; + + list = calloc(1, sizeof(*list)); + if (list != NULL) + list_create(list, sizeof(string_node_t), + offsetof(string_node_t, link)); + + return (list); +} + +static int +sunos_append_to_string_list(string_list_t *list, const char *arg) +{ + string_node_t *np; + + np = calloc(1, sizeof(*np)); + if (!np) + return (-1); + + np->string = strdup(arg); + if (!np->string) { + free(np); + return (-1); + } + + list_insert_tail(list, np); + + return (0); +} + +static void +sunos_free_string_list(string_list_t *list) +{ + string_node_t *np; + + while ((np = list_remove_head(list)) != NULL) { + free(np->string); + free(np); + } + + free(list); +} + +static char ** +sunos_build_argv_list(string_list_t *list) +{ + char **argv_list; + string_node_t *np; + int n; + + n = 1; /* Start at 1 for NULL terminator */ + for (np = list_head(list); np != NULL; np = list_next(list, np)) + n++; + + argv_list = calloc(n, sizeof(char *)); + if (argv_list == NULL) + return NULL; + + n = 0; + for (np = list_head(list); np != NULL; np = list_next(list, np)) + argv_list[n++] = np->string; + + return (argv_list); +} + + +static int +sunos_exec_command(struct libusb_context *ctx, const char *path, + string_list_t *list) +{ + pid_t pid; + int status; + int waitstat; + int exit_status; + char **argv_list; + + argv_list = sunos_build_argv_list(list); + if (argv_list == NULL) + return (-1); + + pid = fork(); + if (pid == 0) { + /* child */ + execv(path, argv_list); + _exit(127); + } else if (pid > 0) { + /* parent */ + do { + waitstat = waitpid(pid, &status, 0); + } while ((waitstat == -1 && errno == EINTR) || + (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status))); + + if (waitstat == 0) { + if (WIFEXITED(status)) + exit_status = WEXITSTATUS(status); + else + exit_status = WTERMSIG(status); + } else { + usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + } else { + /* fork failed */ + usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno)); + exit_status = -1; + } + + free(argv_list); + + return (exit_status); +} + +static int +sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* attach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-a"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor, + dpriv->dev_descr.idProduct); + sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath); + + if (access(dpriv->ugenpath, F_OK) == -1) { + usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver"); + return (LIBUSB_ERROR_IO); + } + + return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv); +} + +static int +sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle, + int interface_number) +{ + struct libusb_context *ctx = HANDLE_CTX(dev_handle); + string_list_t *list; + char path_arg[PATH_MAX]; + sunos_dev_priv_t *dpriv; + int r; + + /* we open the dev in detach driver, so we need close it first. */ + sunos_close(dev_handle); + + dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv; + snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath); + usbi_dbg("%s", path_arg); + + list = sunos_new_string_list(); + if (list == NULL) + return (LIBUSB_ERROR_NO_MEM); + + /* detach ugen driver */ + r = 0; + r |= sunos_append_to_string_list(list, UPDATEDRV); + r |= sunos_append_to_string_list(list, "-d"); /* add rule */ + r |= sunos_append_to_string_list(list, "-i"); /* specific device */ + r |= sunos_append_to_string_list(list, path_arg); /* physical path */ + r |= sunos_append_to_string_list(list, "ugen"); + if (r) { + sunos_free_string_list(list); + return (LIBUSB_ERROR_NO_MEM); + } + + r = sunos_exec_command(ctx, UPDATEDRV_PATH, list); + sunos_free_string_list(list); + if (r < 0) + return (LIBUSB_ERROR_OTHER); + + /* reconfigure the driver node */ + r = 0; + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT); + r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE); + if (r) + usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed"); + + return 0; +} + static int sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) { @@ -93,6 +481,7 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) uint8_t *rdata; struct libusb_device_descriptor *descr; sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; + char match_str[PATH_MAX]; /* Device descriptors */ proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, @@ -137,7 +526,11 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) phypath = di_devfs_path(node); if (phypath) { dpriv->phypath = strdup(phypath); + snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct); + usbi_dbg("match is %s", match_str); + sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath); di_devfs_path_free(phypath); + } else { free(dpriv->raw_cfgdescr); @@ -170,111 +563,98 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) return (LIBUSB_SUCCESS); } - static int sunos_add_devices(di_devlink_t link, void *arg) { struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; struct node_args *nargs; - di_node_t myself, pnode; + di_node_t myself, dn; uint64_t session_id = 0; - uint16_t bdf = 0; + uint64_t sid = 0; + uint64_t bdf = 0; struct libusb_device *dev; sunos_dev_priv_t *devpriv; - const char *path, *newpath; - int n, i; + int n; + int i = 0; int *addr_prop; uint8_t bus_number = 0; + uint32_t * regbuf = NULL; + uint32_t reg; nargs = (struct node_args *)largs->nargs; myself = largs->myself; - if (nargs->last_ugenpath) { - /* the same node's links */ - return (DI_WALK_CONTINUE); - } /* * Construct session ID. - * session ID = ...parent hub addr|hub addr|dev addr. + * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf + * 8 bits 8bits 8 bits 16bits */ - pnode = myself; - i = 0; - while (pnode != DI_NODE_NIL) { - if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) { - /* walk to root */ - uint32_t *regbuf = NULL; - uint32_t reg; + if (myself == DI_NODE_NIL) + return (DI_WALK_CONTINUE); - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", - (int **)®buf); - reg = regbuf[0]; - bdf = (PCI_REG_BUS_G(reg) << 8) | - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - session_id |= (bdf << i * 8); + dn = myself; + /* find the root hub */ + while (di_prop_exists(DDI_DEV_T_ANY, dn, "root-hub") != 1) { + usbi_dbg("find_root_hub:%s", di_devfs_path(dn)); + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, + "assigned-address", &addr_prop); + session_id |= ((addr_prop[0] & 0xff) << i++ * 8); + dn = di_parent_node(dn); + } - /* same as 'unit-address' property */ - bus_number = - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + /* dn is the root hub node */ + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf); + reg = regbuf[0]; + bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); + /* bdf must larger than i*8 bits */ + session_id |= (bdf << i * 8); + bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - usbi_dbg("device bus address=%s:%x", - di_bus_addr(pnode), bus_number); - - break; - } + usbi_dbg("device bus address=%s:%x, name:%s", + di_bus_addr(myself), bus_number, di_node_name(dn)); + usbi_dbg("session id org:%lx", session_id); + /* dn is the usb device */ + for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) { + usbi_dbg("device path:%s", di_devfs_path(dn)); + /* skip hub devices, because its driver can not been unload */ + if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1) + continue; /* usb_addr */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, + n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "assigned-address", &addr_prop); if ((n != 1) || (addr_prop[0] == 0)) { usbi_dbg("cannot get valid usb_addr"); - - return (DI_WALK_CONTINUE); + continue; } - session_id |= ((addr_prop[0] & 0xff) << i * 8); - if (++i > 7) - break; + sid = (session_id << 8) | (addr_prop[0] & 0xff) ; + usbi_dbg("session id %lx", sid); - pnode = di_parent_node(pnode); - } - - path = di_devlink_path(link); - dev = usbi_get_device_by_session_id(nargs->ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(nargs->ctx, session_id); + dev = usbi_get_device_by_session_id(nargs->ctx, sid); if (dev == NULL) { - usbi_dbg("can't alloc device"); + dev = usbi_alloc_device(nargs->ctx, sid); + if (dev == NULL) { + usbi_dbg("can't alloc device"); + continue; + } + devpriv = (sunos_dev_priv_t *)dev->os_priv; + dev->bus_number = bus_number; - return (DI_WALK_TERMINATE); + if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) { + libusb_unref_device(dev); + usbi_dbg("get infomation fail"); + continue; + } + if (usbi_sanitize_device(dev) < 0) { + libusb_unref_device(dev); + usbi_dbg("sanatize failed: "); + return (DI_WALK_TERMINATE); + } + } else { + devpriv = (sunos_dev_priv_t *)dev->os_priv; + usbi_dbg("Dev %s exists", devpriv->ugenpath); } - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if ((newpath = strrchr(path, '/')) == NULL) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - devpriv->ugenpath = strndup(path, strlen(path) - - strlen(newpath)); - dev->bus_number = bus_number; - - if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - if (usbi_sanitize_device(dev) < 0) { - libusb_unref_device(dev); - usbi_dbg("sanatize failed: "); - return (DI_WALK_TERMINATE); - } - } else { - usbi_dbg("Dev %s exists", path); - } - - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if (nargs->last_ugenpath == NULL) { - /* first device */ - nargs->last_ugenpath = devpriv->ugenpath; if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { usbi_dbg("cannot append device"); @@ -285,11 +665,11 @@ sunos_add_devices(di_devlink_t link, void *arg) * hereafter. Front end or app should take care of their ref. */ libusb_unref_device(dev); - } - usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", - devpriv->ugenpath, path, (uint64_t)session_id, - (*nargs->discdevs)->len, bdf); + usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", + devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid, + (*nargs->discdevs)->len, bdf); + } return (DI_WALK_CONTINUE); } @@ -303,14 +683,14 @@ sunos_walk_minor_node_link(di_node_t node, void *args) struct node_args *nargs = (struct node_args *)args; di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; - /* walk each minor to find ugen devices */ + /* walk each minor to find usb devices */ while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { minor_path = di_devfs_minor_path(minor); arg.nargs = args; arg.myself = node; arg.minor = minor; (void) di_devlink_walk(devlink_hdl, - "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path, + "^usb/hub[0-9]+", minor_path, DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); di_devfs_path_free(minor_path); } @@ -496,7 +876,7 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl, usbi_dbg("can't find interface for endpoint 0x%02x", ep_addr); - return (LIBUSB_ERROR_ACCESS); + return (EACCES); } /* create filename */ @@ -603,6 +983,11 @@ sunos_open(struct libusb_device_handle *handle) hpriv->eps[i].statfd = -1; } + if (sunos_kernel_driver_active(handle, 0)) { + /* pretend we can open the device */ + return (LIBUSB_SUCCESS); + } + if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { usbi_dbg("fail: %d", ret); return (ret); @@ -1010,9 +1395,7 @@ void sunos_destroy_device(struct libusb_device *dev) { sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - usbi_dbg(""); - + usbi_dbg("destroy everyting"); free(dpriv->raw_cfgdescr); free(dpriv->ugenpath); free(dpriv->phypath); @@ -1254,7 +1637,7 @@ sunos_usb_get_status(int fd) return (status); } -const struct usbi_os_backend sunos_backend = { +const struct usbi_os_backend usbi_backend = { .name = "Solaris", .caps = 0, .init = sunos_init, @@ -1276,9 +1659,9 @@ const struct usbi_os_backend sunos_backend = { .reset_device = sunos_reset_device, /* TODO */ .alloc_streams = NULL, .free_streams = NULL, - .kernel_driver_active = NULL, - .detach_kernel_driver = NULL, - .attach_kernel_driver = NULL, + .kernel_driver_active = sunos_kernel_driver_active, + .detach_kernel_driver = sunos_detach_kernel_driver, + .attach_kernel_driver = sunos_attach_kernel_driver, .destroy_device = sunos_destroy_device, .submit_transfer = sunos_submit_transfer, .cancel_transfer = sunos_cancel_transfer, diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h similarity index 96% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h index 574166031..52bb3d33a 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h @@ -65,6 +65,12 @@ struct devlink_cbarg { di_minor_t minor; }; +typedef struct walk_link { + char *path; + int len; + char **linkpp; +} walk_link_t; + /* AIO callback args */ struct aio_callback_args{ struct libusb_transfer *transfer; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c similarity index 92% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c index a4f270bbe..16a7578b8 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c @@ -29,7 +29,7 @@ # include # include #elif defined(__APPLE__) -# include +# include #elif defined(__CYGWIN__) # include #endif @@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond, struct timespec timeout; int r; - r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); + r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout); if (r < 0) return r; @@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond, int usbi_get_tid(void) { - int ret = -1; + int ret; #if defined(__ANDROID__) ret = gettid(); #elif defined(__linux__) @@ -69,10 +69,11 @@ int usbi_get_tid(void) real thread support. For 5.1 and earlier, -1 is returned. */ ret = syscall(SYS_getthrid); #elif defined(__APPLE__) - ret = mach_thread_self(); - mach_port_deallocate(mach_task_self(), ret); + ret = (int)pthread_mach_thread_np(pthread_self()); #elif defined(__CYGWIN__) ret = GetCurrentThreadId(); +#else + ret = -1; #endif /* TODO: NetBSD thread ID support */ return ret; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h new file mode 100644 index 000000000..9f1ef94bc --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h @@ -0,0 +1,102 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright © 2010 Peter Stuge + * + * This 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 2.1 of the License, or (at your option) any later version. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_THREADS_POSIX_H +#define LIBUSB_THREADS_POSIX_H + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t usbi_mutex_static_t; +static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} + +typedef pthread_mutex_t usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + return pthread_mutex_init(mutex, NULL); +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_lock(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_unlock(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return pthread_mutex_trylock(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + (void)pthread_mutex_destroy(mutex); +} + +typedef pthread_cond_t usbi_cond_t; +static inline void usbi_cond_init(pthread_cond_t *cond) +{ + (void)pthread_cond_init(cond, NULL); +} +static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + return pthread_cond_wait(cond, mutex); +} +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv); +static inline void usbi_cond_broadcast(usbi_cond_t *cond) +{ + (void)pthread_cond_broadcast(cond); +} +static inline void usbi_cond_destroy(usbi_cond_t *cond) +{ + (void)pthread_cond_destroy(cond); +} + +typedef pthread_key_t usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + (void)pthread_key_create(key, NULL); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return pthread_getspecific(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)pthread_setspecific(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)pthread_key_delete(key); +} + +int usbi_get_tid(void); + +#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c new file mode 100644 index 000000000..409c49055 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c @@ -0,0 +1,126 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright © 2010 Michael Plante + * + * This 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 2.1 of the License, or (at your option) any later version. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "libusbi.h" + +struct usbi_cond_perthread { + struct list_head list; + HANDLE event; +}; + +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex) +{ + while (InterlockedExchange(mutex, 1L) == 1L) + SleepEx(0, TRUE); +} + +void usbi_cond_init(usbi_cond_t *cond) +{ + list_init(&cond->waiters); + list_init(&cond->not_waiting); +} + +static int usbi_cond_intwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, DWORD timeout_ms) +{ + struct usbi_cond_perthread *pos; + DWORD r; + + // Same assumption as usbi_cond_broadcast() holds + if (list_empty(&cond->not_waiting)) { + pos = malloc(sizeof(*pos)); + if (pos == NULL) + return ENOMEM; // This errno is not POSIX-allowed. + pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. + if (pos->event == NULL) { + free(pos); + return ENOMEM; + } + } else { + pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list); + list_del(&pos->list); // remove from not_waiting list. + // Ensure the event is clear before waiting + WaitForSingleObject(pos->event, 0); + } + + list_add(&pos->list, &cond->waiters); + + LeaveCriticalSection(mutex); + r = WaitForSingleObject(pos->event, timeout_ms); + EnterCriticalSection(mutex); + + list_del(&pos->list); + list_add(&pos->list, &cond->not_waiting); + + if (r == WAIT_OBJECT_0) + return 0; + else if (r == WAIT_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; +} + +// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + return usbi_cond_intwait(cond, mutex, INFINITE); +} + +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, const struct timeval *tv) +{ + DWORD millis; + + millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); + /* round up to next millisecond */ + if (tv->tv_usec % 1000) + millis++; + return usbi_cond_intwait(cond, mutex, millis); +} + +void usbi_cond_broadcast(usbi_cond_t *cond) +{ + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + struct usbi_cond_perthread *pos; + + list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) + SetEvent(pos->event); + // The wait function will remove its respective item from the list. +} + +void usbi_cond_destroy(usbi_cond_t *cond) +{ + // This assumes no one is using this anymore. The check MAY NOT BE safe. + struct usbi_cond_perthread *pos, *next; + + if (!list_empty(&cond->waiters)) + return; // (!see above!) + list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) { + CloseHandle(pos->event); + list_del(&pos->list); + free(pos); + } +} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h similarity index 53% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h index e97ee7875..409de2d0e 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h @@ -21,17 +21,40 @@ #ifndef LIBUSB_THREADS_WINDOWS_H #define LIBUSB_THREADS_WINDOWS_H -#define usbi_mutex_static_t volatile LONG -#define USBI_MUTEX_INITIALIZER 0 +#define USBI_MUTEX_INITIALIZER 0L +#ifdef _WIN32_WCE +typedef LONG usbi_mutex_static_t; +#else +typedef volatile LONG usbi_mutex_static_t; +#endif +void usbi_mutex_static_lock(usbi_mutex_static_t *mutex); +static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) +{ + InterlockedExchange(mutex, 0L); +} -#define usbi_mutex_t HANDLE - -typedef struct usbi_cond { - // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread terminates. - struct list_head waiters; - struct list_head not_waiting; -} usbi_cond_t; +typedef CRITICAL_SECTION usbi_mutex_t; +static inline int usbi_mutex_init(usbi_mutex_t *mutex) +{ + InitializeCriticalSection(mutex); + return 0; +} +static inline void usbi_mutex_lock(usbi_mutex_t *mutex) +{ + EnterCriticalSection(mutex); +} +static inline void usbi_mutex_unlock(usbi_mutex_t *mutex) +{ + LeaveCriticalSection(mutex); +} +static inline int usbi_mutex_trylock(usbi_mutex_t *mutex) +{ + return !TryEnterCriticalSection(mutex); +} +static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) +{ + DeleteCriticalSection(mutex); +} // We *were* getting timespec from pthread.h: #if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) @@ -45,32 +68,44 @@ struct timespec { // We *were* getting ETIMEDOUT from pthread.h: #ifndef ETIMEDOUT -# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif -#define usbi_tls_key_t DWORD +typedef struct usbi_cond { + // Every time a thread touches the CV, it winds up in one of these lists. + // It stays there until the CV is destroyed, even if the thread terminates. + struct list_head waiters; + struct list_head not_waiting; +} usbi_cond_t; -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); - -int usbi_mutex_init(usbi_mutex_t *mutex); -int usbi_mutex_lock(usbi_mutex_t *mutex); -int usbi_mutex_unlock(usbi_mutex_t *mutex); -int usbi_mutex_trylock(usbi_mutex_t *mutex); -int usbi_mutex_destroy(usbi_mutex_t *mutex); - -int usbi_cond_init(usbi_cond_t *cond); +void usbi_cond_init(usbi_cond_t *cond); int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); int usbi_cond_timedwait(usbi_cond_t *cond, usbi_mutex_t *mutex, const struct timeval *tv); -int usbi_cond_broadcast(usbi_cond_t *cond); -int usbi_cond_destroy(usbi_cond_t *cond); +void usbi_cond_broadcast(usbi_cond_t *cond); +void usbi_cond_destroy(usbi_cond_t *cond); -int usbi_tls_key_create(usbi_tls_key_t *key); -void *usbi_tls_key_get(usbi_tls_key_t key); -int usbi_tls_key_set(usbi_tls_key_t key, void *value); -int usbi_tls_key_delete(usbi_tls_key_t key); +typedef DWORD usbi_tls_key_t; +static inline void usbi_tls_key_create(usbi_tls_key_t *key) +{ + *key = TlsAlloc(); +} +static inline void *usbi_tls_key_get(usbi_tls_key_t key) +{ + return TlsGetValue(key); +} +static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr) +{ + (void)TlsSetValue(key, ptr); +} +static inline void usbi_tls_key_delete(usbi_tls_key_t key) +{ + (void)TlsFree(key); +} -int usbi_get_tid(void); +static inline int usbi_get_tid(void) +{ + return (int)GetCurrentThreadId(); +} #endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/wince_usb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c similarity index 94% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/wince_usb.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c index 0d466b8c9..a0f35e93e 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/wince_usb.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.c @@ -31,7 +31,7 @@ #include "wince_usb.h" // Global variables -int windows_version = WINDOWS_CE; +int errno = 0; static uint64_t hires_frequency, hires_ticks_to_ps; static HANDLE driver_handle = INVALID_HANDLE_VALUE; static int concurrent_usage = -1; @@ -109,7 +109,7 @@ static int translate_driver_error(DWORD error) } } -static int init_dllimports(void) +static BOOL init_dllimports(void) { DLL_GET_HANDLE(ceusbkwrapper); DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); @@ -135,7 +135,7 @@ static int init_dllimports(void) DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); - return LIBUSB_SUCCESS; + return TRUE; } static void exit_dllimports(void) @@ -186,11 +186,8 @@ static int wince_init(struct libusb_context *ctx) // NB: concurrent usage supposes that init calls are equally balanced with // exit calls. If init is called more than exit, we will not exit properly if ( ++concurrent_usage == 0 ) { // First init? - // Initialize pollable file descriptors - init_polling(); - // Load DLL imports - if (init_dllimports() != LIBUSB_SUCCESS) { + if (!init_dllimports()) { usbi_err(ctx, "could not resolve DLL functions"); r = LIBUSB_ERROR_NOT_SUPPORTED; goto init_exit; @@ -223,7 +220,6 @@ static int wince_init(struct libusb_context *ctx) init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? exit_dllimports(); - exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); @@ -239,10 +235,11 @@ init_exit: // Holds semaphore here. return r; } -static void wince_exit(void) +static void wince_exit(struct libusb_context *ctx) { HANDLE semaphore; TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); @@ -259,7 +256,6 @@ static void wince_exit(void) // Only works if exits and inits are balanced exactly if (--concurrent_usage < 0) { // Last exit exit_dllimports(); - exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); @@ -328,7 +324,7 @@ static int wince_get_device_list( } new_devices = discovered_devs_append(new_devices, dev); - if (!discdevs) { + if (!new_devices) { r = LIBUSB_ERROR_NO_MEM; goto err_out; } @@ -541,12 +537,9 @@ static void wince_destroy_device(struct libusb_device *dev) static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) { struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); - // No need to cancel transfer as it is either complete or abandoned - wfd.itransfer = NULL; - CloseHandle(wfd.handle); - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; } static int wince_cancel_transfer(struct usbi_transfer *itransfer) @@ -570,11 +563,10 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer BOOL direction_in, ret; struct winfd wfd; DWORD flags; - HANDLE eventHandle; PUKW_CONTROL_HEADER setup = NULL; const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; + int r; - transfer_priv->pollable_fd = INVALID_WINFD; if (control_transfer) { setup = (PUKW_CONTROL_HEADER) transfer->buffer; direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; @@ -584,19 +576,18 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; flags |= UKW_TF_SHORT_TRANSFER_OK; - eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (eventHandle == NULL) { - usbi_err(ctx, "Failed to create event for async transfer"); + wfd = usbi_create_fd(); + if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; - } - wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); - if (wfd.fd < 0) { - CloseHandle(eventHandle); - return LIBUSB_ERROR_NO_MEM; + r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT); + if (r) { + usbi_close(wfd.fd); + return r; } transfer_priv->pollable_fd = wfd; + if (control_transfer) { // Split out control setup header and data buffer DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); @@ -612,19 +603,16 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer int libusbErr = translate_driver_error(GetLastError()); usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); - wince_clear_transfer_priv(itransfer); + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; return libusbErr; } - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); + return LIBUSB_SUCCESS; } -static int wince_submit_iso_transfer(struct usbi_transfer *itransfer) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - static int wince_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); @@ -635,7 +623,6 @@ static int wince_submit_transfer(struct usbi_transfer *itransfer) case LIBUSB_TRANSFER_TYPE_INTERRUPT: return wince_submit_control_or_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return wince_submit_iso_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK_STREAM: return LIBUSB_ERROR_NOT_SUPPORTED; default: @@ -763,7 +750,7 @@ static int wince_handle_events( struct wince_transfer_priv* transfer_priv = NULL; POLL_NFDS_TYPE i = 0; BOOL found = FALSE; - struct usbi_transfer *transfer; + struct usbi_transfer *itransfer; DWORD io_size, io_result; int r = LIBUSB_SUCCESS; @@ -780,8 +767,8 @@ static int wince_handle_events( // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer usbi_mutex_lock(&ctx->flying_transfers_lock); - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - transfer_priv = usbi_transfer_get_os_priv(transfer); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_priv = usbi_transfer_get_os_priv(itransfer); if (transfer_priv->pollable_fd.fd == fds[i].fd) { found = TRUE; break; @@ -796,7 +783,7 @@ static int wince_handle_events( // let handle_callback free the event using the transfer wfd // If you don't use the transfer wfd, you run a risk of trying to free a // newly allocated wfd that took the place of the one from the transfer. - wince_handle_callback(transfer, io_result, io_size); + wince_handle_callback(itransfer, io_result, io_size); } else if (found) { usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); r = LIBUSB_ERROR_OTHER; @@ -848,11 +835,12 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp) } } -const struct usbi_os_backend wince_backend = { +const struct usbi_os_backend usbi_backend = { "Windows CE", 0, wince_init, wince_exit, + NULL, /* set_option() */ wince_get_device_list, NULL, /* hotplug_poll */ @@ -893,6 +881,7 @@ const struct usbi_os_backend wince_backend = { NULL, /* handle_transfer_completion() */ wince_clock_gettime, + 0, sizeof(struct wince_device_priv), 0, sizeof(struct wince_transfer_priv), diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/wince_usb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/wince_usb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/wince_usb.h diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h similarity index 82% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/windows_common.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h index 55344ca26..b1725c2e3 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_common.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_common.h @@ -68,31 +68,35 @@ /* * Macros for handling DLL themselves */ +#define DLL_HANDLE_NAME(name) __dll_##name##_handle + #define DLL_DECLARE_HANDLE(name) \ - static HMODULE __dll_##name##_handle = NULL + static HMODULE DLL_HANDLE_NAME(name) = NULL #define DLL_GET_HANDLE(name) \ do { \ - __dll_##name##_handle = DLL_LOAD_LIBRARY(name); \ - if (!__dll_##name##_handle) \ - return LIBUSB_ERROR_OTHER; \ + DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \ + if (!DLL_HANDLE_NAME(name)) \ + return FALSE; \ } while (0) #define DLL_FREE_HANDLE(name) \ do { \ - if (__dll_##name##_handle) { \ - FreeLibrary(__dll_##name##_handle); \ - __dll_##name##_handle = NULL; \ + if (DLL_HANDLE_NAME(name)) { \ + FreeLibrary(DLL_HANDLE_NAME(name)); \ + DLL_HANDLE_NAME(name) = NULL; \ } \ - } while(0) + } while (0) /* * Macros for handling functions within a DLL */ +#define DLL_FUNC_NAME(name) __dll_##name##_func_t + #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ - typedef ret (api * __dll_##name##_func_t)args; \ - static __dll_##name##_func_t prefixname = NULL + typedef ret (api * DLL_FUNC_NAME(name))args; \ + static DLL_FUNC_NAME(name) prefixname = NULL #define DLL_DECLARE_FUNC(api, ret, name, args) \ DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) @@ -101,22 +105,22 @@ #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ do { \ - HMODULE h = __dll_##dll##_handle; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + HMODULE h = DLL_HANDLE_NAME(dll); \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name)); \ if (prefixname) \ break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ if (prefixname) \ break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ + prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \ DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ if (prefixname) \ break; \ if (ret_on_failure) \ - return LIBUSB_ERROR_NOT_FOUND; \ - } while(0) + return FALSE; \ + } while (0) #define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c similarity index 52% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c index d935394a6..92dbde5a8 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.c @@ -32,6 +32,14 @@ #include "windows_common.h" #include "windows_nt_common.h" +// Public +BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); +enum windows_version windows_version = WINDOWS_UNDEFINED; + + // Global variables for init/exit +static unsigned int init_count = 0; +static bool usbdk_available = false; + // Global variables for clock_gettime mechanism static uint64_t hires_ticks_to_ps; static uint64_t hires_frequency; @@ -50,6 +58,11 @@ struct timer_request { static HANDLE timer_thread = NULL; static DWORD timer_thread_id = 0; +/* Kernel32 dependencies */ +DLL_DECLARE_HANDLE(Kernel32); +/* This call is only available from XP SP2 */ +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); + /* User32 dependencies */ DLL_DECLARE_HANDLE(User32); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); @@ -111,6 +124,11 @@ const char *windows_error_str(DWORD error_code) } #endif +static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx) +{ + return (struct windows_context_priv *)ctx->os_priv; +} + /* Hash table functions - modified From glibc 2.3.2: [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 [Knuth] The Art of Computer Programming, part 3 (6.4) */ @@ -123,7 +141,7 @@ typedef struct htab_entry { } htab_entry; static htab_entry *htab_table = NULL; -static usbi_mutex_t htab_mutex = NULL; +static usbi_mutex_t htab_mutex; static unsigned long htab_filled; /* Before using the hash table we must allocate memory for it. @@ -256,35 +274,46 @@ out_unlock: return idx; } -static int windows_init_dlls(void) +/* +* Make a transfer complete synchronously +*/ +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size) { + overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + overlapped->InternalHigh = size; + SetEvent(overlapped->hEvent); +} + +static BOOL windows_init_dlls(void) +{ + DLL_GET_HANDLE(Kernel32); + DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); + pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED)) + GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx"); + usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : ""); + DLL_GET_HANDLE(User32); DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); - return LIBUSB_SUCCESS; + return TRUE; } static void windows_exit_dlls(void) { + DLL_FREE_HANDLE(Kernel32); DLL_FREE_HANDLE(User32); } static bool windows_init_clock(struct libusb_context *ctx) { DWORD_PTR affinity, dummy; - HANDLE event = NULL; + HANDLE event; LARGE_INTEGER li_frequency; int i; if (QueryPerformanceFrequency(&li_frequency)) { - // Load DLL imports - if (windows_init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - return false; - } - // The hires frequency can go as high as 4 GHz, so we'll use a conversion // to picoseconds to compute the tv_nsecs part in clock_gettime hires_frequency = li_frequency.QuadPart; @@ -340,7 +369,7 @@ static bool windows_init_clock(struct libusb_context *ctx) return true; } -void windows_destroy_clock(void) +static void windows_destroy_clock(void) { if (timer_thread) { // actually the signal to quit the thread. @@ -357,6 +386,110 @@ void windows_destroy_clock(void) } } +/* Windows version detection */ +static BOOL is_x64(void) +{ + BOOL ret = FALSE; + + // Detect if we're running a 32 or 64 bit system + if (sizeof(uintptr_t) < 8) { + if (pIsWow64Process != NULL) + pIsWow64Process(GetCurrentProcess(), &ret); + } else { + ret = TRUE; + } + + return ret; +} + +static void get_windows_version(void) +{ + OSVERSIONINFOEXA vi, vi2; + const char *arch, *w = NULL; + unsigned major, minor, version; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + windows_version = WINDOWS_UNDEFINED; + + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) + return; + } + + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return; + + if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) { + // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx + + major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (major = vi.dwMajorVersion; major <= 9; major++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMajorVersion = major; + if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) + continue; + + if (vi.dwMajorVersion < major) { + vi.dwMajorVersion = major; + vi.dwMinorVersion = 0; + } + + minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (minor = vi.dwMinorVersion; minor <= 9; minor++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMinorVersion = minor; + if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) + continue; + + vi.dwMinorVersion = minor; + break; + } + + break; + } + } + + if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf)) + return; + + ws = (vi.wProductType <= VER_NT_WORKSTATION); + version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (version) { + case 0x50: windows_version = WINDOWS_2000; w = "2000"; break; + case 0x51: windows_version = WINDOWS_XP; w = "XP"; break; + case 0x52: windows_version = WINDOWS_2003; w = "2003"; break; + case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break; + case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break; + case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break; + case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break; + case 0x64: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break; + default: + if (version < 0x50) { + return; + } else { + windows_version = WINDOWS_11_OR_LATER; + w = "11 or later"; + } + } + + arch = is_x64() ? "64-bit" : "32-bit"; + + if (vi.wServicePackMinor) + usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch); + else if (vi.wServicePackMajor) + usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch); + else + usbi_dbg("Windows %s %s", w, arch); +} + /* * Monotonic and real time functions */ @@ -401,7 +534,379 @@ static unsigned __stdcall windows_clock_gettime_threaded(void *param) } } -int windows_clock_gettime(int clk_id, struct timespec *tp) +static void windows_transfer_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + int status, istatus; + + usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size); + + switch (io_result) { + case NO_ERROR: + status = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + break; + case ERROR_GEN_FAILURE: + usbi_dbg("detected endpoint stall"); + status = LIBUSB_TRANSFER_STALL; + break; + case ERROR_SEM_TIMEOUT: + usbi_dbg("detected semaphore timeout"); + status = LIBUSB_TRANSFER_TIMED_OUT; + break; + case ERROR_OPERATION_ABORTED: + istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size); + if (istatus != LIBUSB_TRANSFER_COMPLETED) + usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); + + usbi_dbg("detected operation aborted"); + status = LIBUSB_TRANSFER_CANCELLED; + break; + case ERROR_FILE_NOT_FOUND: + usbi_dbg("detected device removed"); + status = LIBUSB_TRANSFER_NO_DEVICE; + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result)); + status = LIBUSB_TRANSFER_ERROR; + break; + } + backend->clear_transfer_priv(itransfer); // Cancel polling + if (status == LIBUSB_TRANSFER_CANCELLED) + usbi_handle_transfer_cancellation(itransfer); + else + usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); +} + +static void windows_handle_callback(const struct windows_backend *backend, + struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + windows_transfer_callback(backend, itransfer, io_result, io_size); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); + break; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + } +} + +static int windows_init(struct libusb_context *ctx) +{ + struct windows_context_priv *priv = _context_priv(ctx); + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + int r = LIBUSB_ERROR_OTHER; + bool winusb_backend_init = false; + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) { + usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_MEM; + } + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore's release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); + CloseHandle(semaphore); + return LIBUSB_ERROR_NO_MEM; + } + + // NB: concurrent usage supposes that init calls are equally balanced with + // exit calls. If init is called more than exit, we will not exit properly + if (++init_count == 1) { // First init? + // Load DLL imports + if (!windows_init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + goto init_exit; + } + + get_windows_version(); + + if (windows_version == WINDOWS_UNDEFINED) { + usbi_err(ctx, "failed to detect Windows version"); + r = LIBUSB_ERROR_NOT_SUPPORTED; + goto init_exit; + } + + if (!windows_init_clock(ctx)) + goto init_exit; + + if (!htab_create(ctx)) + goto init_exit; + + r = winusb_backend.init(ctx); + if (r != LIBUSB_SUCCESS) + goto init_exit; + winusb_backend_init = true; + + r = usbdk_backend.init(ctx); + if (r == LIBUSB_SUCCESS) { + usbi_dbg("UsbDk backend is available"); + usbdk_available = true; + } else { + usbi_info(ctx, "UsbDk backend is not available"); + // Do not report this as an error + r = LIBUSB_SUCCESS; + } + } + + // By default, new contexts will use the WinUSB backend + priv->backend = &winusb_backend; + + r = LIBUSB_SUCCESS; + +init_exit: // Holds semaphore here + if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed? + if (winusb_backend_init) + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + --init_count; + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); + return r; +} + +static void windows_exit(struct libusb_context *ctx) +{ + HANDLE semaphore; + char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' + UNUSED(ctx); + + sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); + semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); + if (semaphore == NULL) + return; + + // A successful wait brings our semaphore count to 0 (unsignaled) + // => any concurent wait stalls until the semaphore release + if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { + CloseHandle(semaphore); + return; + } + + // Only works if exits and inits are balanced exactly + if (--init_count == 0) { // Last exit + if (usbdk_available) { + usbdk_backend.exit(ctx); + usbdk_available = false; + } + winusb_backend.exit(ctx); + htab_destroy(); + windows_destroy_clock(); + windows_exit_dlls(); + } + + ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 + CloseHandle(semaphore); +} + +static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap) +{ + struct windows_context_priv *priv = _context_priv(ctx); + + UNUSED(ap); + + switch (option) { + case LIBUSB_OPTION_USE_USBDK: + if (usbdk_available) { + usbi_dbg("switching context %p to use UsbDk backend", ctx); + priv->backend = &usbdk_backend; + } else { + usbi_err(ctx, "UsbDk backend not available"); + return LIBUSB_ERROR_NOT_FOUND; + } + return LIBUSB_SUCCESS; + default: + return LIBUSB_ERROR_NOT_SUPPORTED; + } + +} + +static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs) +{ + struct windows_context_priv *priv = _context_priv(ctx); + return priv->backend->get_device_list(ctx, discdevs); +} + +static int windows_open(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->open(dev_handle); +} + +static void windows_close(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + priv->backend->close(dev_handle); +} + +static int windows_get_device_descriptor(struct libusb_device *dev, + unsigned char *buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_device_descriptor(dev, buffer); +} + +static int windows_get_active_config_descriptor(struct libusb_device *dev, + unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_active_config_descriptor(dev, buffer, len); +} + +static int windows_get_config_descriptor(struct libusb_device *dev, + uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor(dev, config_index, buffer, len); +} + +static int windows_get_config_descriptor_by_value(struct libusb_device *dev, + uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + *host_endian = 0; + return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer); +} + +static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->get_configuration(dev_handle, config); +} + +static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_configuration(dev_handle, config); +} + +static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->claim_interface(dev_handle, interface_number); +} + +static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->release_interface(dev_handle, interface_number); +} + +static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting); +} + +static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->clear_halt(dev_handle, endpoint); +} + +static int windows_reset_device(struct libusb_device_handle *dev_handle) +{ + struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); + return priv->backend->reset_device(dev_handle); +} + +static void windows_destroy_device(struct libusb_device *dev) +{ + struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev)); + priv->backend->destroy_device(dev); +} + +static int windows_submit_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->submit_transfer(itransfer); +} + +static int windows_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + return priv->backend->cancel_transfer(itransfer); +} + +static void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer)); + priv->backend->clear_transfer_priv(itransfer); +} + +static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) +{ + struct windows_context_priv *priv = _context_priv(ctx); + struct usbi_transfer *itransfer; + DWORD io_size, io_result; + POLL_NFDS_TYPE i; + bool found; + int transfer_fd; + int r = LIBUSB_SUCCESS; + + usbi_mutex_lock(&ctx->open_devs_lock); + for (i = 0; i < nfds && num_ready > 0; i++) { + + usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); + + if (!fds[i].revents) + continue; + + num_ready--; + + // Because a Windows OVERLAPPED is used for poll emulation, + // a pollable fd is created and stored with each transfer + found = false; + transfer_fd = -1; + usbi_mutex_lock(&ctx->flying_transfers_lock); + list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { + transfer_fd = priv->backend->get_transfer_fd(itransfer); + if (transfer_fd == fds[i].fd) { + found = true; + break; + } + } + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + if (found) { + priv->backend->get_overlapped_result(itransfer, &io_result, &io_size); + + usbi_remove_pollfd(ctx, transfer_fd); + + // let handle_callback free the event using the transfer wfd + // If you don't use the transfer wfd, you run a risk of trying to free a + // newly allocated wfd that took the place of the one from the transfer. + windows_handle_callback(priv->backend, itransfer, io_result, io_size); + } else { + usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd); + r = LIBUSB_ERROR_NOT_FOUND; + break; + } + } + usbi_mutex_unlock(&ctx->open_devs_lock); + + return r; +} + +static int windows_clock_gettime(int clk_id, struct timespec *tp) { struct timer_request request; #if !defined(_MSC_VER) || (_MSC_VER < 1900) @@ -460,132 +965,44 @@ int windows_clock_gettime(int clk_id, struct timespec *tp) } } -static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - int status, istatus; - - usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); - - switch (io_result) { - case NO_ERROR: - status = windows_copy_transfer_data(itransfer, io_size); - break; - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - istatus = windows_copy_transfer_data(itransfer, io_size); - if (istatus != LIBUSB_TRANSFER_COMPLETED) - usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - windows_clear_transfer_priv(itransfer); // Cancel polling - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_transfer_callback(itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - POLL_NFDS_TYPE i; - bool found = false; - struct usbi_transfer *transfer; - struct winfd *pollable_fd = NULL; - DWORD io_size, io_result; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - found = false; - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - pollable_fd = windows_get_fd(transfer); - if (pollable_fd->fd == fds[i].fd) { - found = true; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found) { - windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size); - - usbi_remove_pollfd(ctx, pollable_fd->fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - windows_handle_callback(transfer, io_result, io_size); - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -int windows_common_init(struct libusb_context *ctx) -{ - if (!windows_init_clock(ctx)) - goto error_roll_back; - - if (!htab_create(ctx)) - goto error_roll_back; - - return LIBUSB_SUCCESS; - -error_roll_back: - windows_common_exit(); - return LIBUSB_ERROR_NO_MEM; -} - -void windows_common_exit(void) -{ - htab_destroy(); - windows_destroy_clock(); - windows_exit_dlls(); -} +// NB: MSVC6 does not support named initializers. +const struct usbi_os_backend usbi_backend = { + "Windows", + USBI_CAP_HAS_HID_ACCESS, + windows_init, + windows_exit, + windows_set_option, + windows_get_device_list, + NULL, /* hotplug_poll */ + windows_open, + windows_close, + windows_get_device_descriptor, + windows_get_active_config_descriptor, + windows_get_config_descriptor, + windows_get_config_descriptor_by_value, + windows_get_configuration, + windows_set_configuration, + windows_claim_interface, + windows_release_interface, + windows_set_interface_altsetting, + windows_clear_halt, + windows_reset_device, + NULL, /* alloc_streams */ + NULL, /* free_streams */ + NULL, /* dev_mem_alloc */ + NULL, /* dev_mem_free */ + NULL, /* kernel_driver_active */ + NULL, /* detach_kernel_driver */ + NULL, /* attach_kernel_driver */ + windows_destroy_device, + windows_submit_transfer, + windows_cancel_transfer, + windows_clear_transfer_priv, + windows_handle_events, + NULL, /* handle_transfer_completion */ + windows_clock_gettime, + sizeof(struct windows_context_priv), + sizeof(union windows_device_priv), + sizeof(union windows_device_handle_priv), + sizeof(union windows_transfer_priv), +}; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h new file mode 100644 index 000000000..e155b5d3e --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_common.h @@ -0,0 +1,110 @@ +/* + * Windows backend common header for libusb 1.0 + * + * This file brings together header code common between + * the desktop Windows backends. + * Copyright © 2012-2013 RealVNC Ltd. + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen + * + * This 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 2.1 of the License, or (at your option) any later version. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "windows_nt_shared_types.h" + + /* Windows versions */ +enum windows_version { + WINDOWS_UNDEFINED, + WINDOWS_2000, + WINDOWS_XP, + WINDOWS_2003, // Also XP x64 + WINDOWS_VISTA, + WINDOWS_7, + WINDOWS_8, + WINDOWS_8_1, + WINDOWS_10, + WINDOWS_11_OR_LATER +}; + +extern enum windows_version windows_version; + +/* This call is only available from Vista */ +extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); + +struct windows_backend { + int (*init)(struct libusb_context *ctx); + void (*exit)(struct libusb_context *ctx); + int (*get_device_list)(struct libusb_context *ctx, + struct discovered_devs **discdevs); + int (*open)(struct libusb_device_handle *dev_handle); + void (*close)(struct libusb_device_handle *dev_handle); + int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer); + int (*get_active_config_descriptor)(struct libusb_device *device, + unsigned char *buffer, size_t len); + int (*get_config_descriptor)(struct libusb_device *device, + uint8_t config_index, unsigned char *buffer, size_t len); + int (*get_config_descriptor_by_value)(struct libusb_device *device, + uint8_t bConfigurationValue, unsigned char **buffer); + int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); + int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); + int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, + int interface_number, int altsetting); + int (*clear_halt)(struct libusb_device_handle *dev_handle, + unsigned char endpoint); + int (*reset_device)(struct libusb_device_handle *dev_handle); + void (*destroy_device)(struct libusb_device *dev); + int (*submit_transfer)(struct usbi_transfer *itransfer); + int (*cancel_transfer)(struct usbi_transfer *itransfer); + void (*clear_transfer_priv)(struct usbi_transfer *itransfer); + int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size); + int (*get_transfer_fd)(struct usbi_transfer *itransfer); + void (*get_overlapped_result)(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size); +}; + +struct windows_context_priv { + const struct windows_backend *backend; +}; + +union windows_device_priv { + struct usbdk_device_priv usbdk_priv; + struct winusb_device_priv winusb_priv; +}; + +union windows_device_handle_priv { + struct usbdk_device_handle_priv usbdk_priv; + struct winusb_device_handle_priv winusb_priv; +}; + +union windows_transfer_priv { + struct usbdk_transfer_priv usbdk_priv; + struct winusb_transfer_priv winusb_priv; +}; + +extern const struct windows_backend usbdk_backend; +extern const struct windows_backend winusb_backend; + +unsigned long htab_hash(const char *str); +void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size); + +#if defined(ENABLE_LOGGING) +const char *windows_error_str(DWORD error_code); +#endif diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h new file mode 100644 index 000000000..68bf261d5 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_nt_shared_types.h @@ -0,0 +1,138 @@ +#pragma once + +#include "windows_common.h" + +#include + +typedef struct USB_DEVICE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + USHORT idVendor; + USHORT idProduct; + USHORT bcdDevice; + UCHAR iManufacturer; + UCHAR iProduct; + UCHAR iSerialNumber; + UCHAR bNumConfigurations; +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct USB_CONFIGURATION_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +#include + +#define MAX_DEVICE_ID_LEN 200 + +typedef struct USB_DK_DEVICE_ID { + WCHAR DeviceID[MAX_DEVICE_ID_LEN]; + WCHAR InstanceID[MAX_DEVICE_ID_LEN]; +} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; + +typedef struct USB_DK_DEVICE_INFO { + USB_DK_DEVICE_ID ID; + ULONG64 FilterID; + ULONG64 Port; + ULONG64 Speed; + USB_DEVICE_DESCRIPTOR DeviceDescriptor; +} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; + +typedef struct USB_DK_ISO_TRANSFER_RESULT { + ULONG64 ActualLength; + ULONG64 TransferResult; +} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; + +typedef struct USB_DK_GEN_TRANSFER_RESULT { + ULONG64 BytesTransferred; + ULONG64 UsbdStatus; // USBD_STATUS code +} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_RESULT { + USB_DK_GEN_TRANSFER_RESULT GenResult; + PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT +} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; + +typedef struct USB_DK_TRANSFER_REQUEST { + ULONG64 EndpointAddress; + PVOID64 Buffer; + ULONG64 BufferLength; + ULONG64 TransferType; + ULONG64 IsochronousPacketsArraySize; + PVOID64 IsochronousPacketsArray; + USB_DK_TRANSFER_RESULT Result; +} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; + +struct usbdk_device_priv { + USB_DK_DEVICE_INFO info; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; + HANDLE redirector_handle; + HANDLE system_handle; + uint8_t active_configuration; +}; + +struct winusb_device_priv { + bool initialized; + bool root_hub; + uint8_t active_config; + uint8_t depth; // distance to HCD + const struct windows_usb_api_backend *apib; + char *dev_id; + char *path; // device interface path + int sub_api; // for WinUSB-like APIs + struct { + char *path; // each interface needs a device interface path, + const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support), + int sub_api; + int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) + uint8_t *endpoint; + bool restricted_functionality; // indicates if the interface functionality is restricted + // by Windows (eg. HID keyboards or mice cannot do R/W) + } usb_interface[USB_MAXINTERFACES]; + struct hid_device_priv *hid; + USB_DEVICE_DESCRIPTOR dev_descriptor; + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors +}; + +struct usbdk_device_handle_priv { + // Not currently used + char dummy; +}; + +struct winusb_device_handle_priv { + int active_interface; + struct { + HANDLE dev_handle; // WinUSB needs an extra handle for the file + HANDLE api_handle; // used by the API to communicate with the device + } interface_handle[USB_MAXINTERFACES]; + int autoclaim_count[USB_MAXINTERFACES]; // For auto-release +}; + +struct usbdk_transfer_priv { + USB_DK_TRANSFER_REQUEST request; + struct winfd pollable_fd; + HANDLE system_handle; + PULONG64 IsochronousPacketsArray; + PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; +}; + +struct winusb_transfer_priv { + struct winfd pollable_fd; + HANDLE handle; + uint8_t interface_number; + uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID + uint8_t *hid_dest; // transfer buffer destination, required for HID + size_t hid_expected_size; + void *iso_context; +}; diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c similarity index 70% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.c rename to vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c index 7cc579387..fbccbd5cf 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.c +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.c @@ -23,22 +23,12 @@ #include -#if defined(USE_USBDK) - #include -#include #include #include "libusbi.h" #include "windows_common.h" #include "windows_nt_common.h" - -#define ULONG64 uint64_t -#define PVOID64 uint64_t - -typedef CONST WCHAR *PCWCHAR; -#define wcsncpy_s wcsncpy - #include "windows_usbdk.h" #if !defined(STATUS_SUCCESS) @@ -55,7 +45,7 @@ typedef LONG NTSTATUS; #endif #if !defined(USBD_SUCCESS) -typedef int32_t USBD_STATUS; +typedef LONG USBD_STATUS; #define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) #define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) #define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) @@ -66,22 +56,6 @@ typedef int32_t USBD_STATUS; #define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) #endif -static int concurrent_usage = -1; - -struct usbdk_device_priv { - USB_DK_DEVICE_INFO info; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; - HANDLE redirector_handle; - uint8_t active_configuration; -}; - -struct usbdk_transfer_priv { - USB_DK_TRANSFER_REQUEST request; - struct winfd pollable_fd; - PULONG64 IsochronousPacketsArray; - PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; -}; - static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) { return (struct usbdk_device_priv *)dev->os_priv; @@ -115,7 +89,7 @@ static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); if (api_ptr == NULL) - usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); + usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0)); return api_ptr; } @@ -132,7 +106,7 @@ static int load_usbdk_helper_dll(struct libusb_context *ctx) { usbdk_helper.module = LoadLibraryA("UsbDkHelper"); if (usbdk_helper.module == NULL) { - usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError()); + usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0)); return LIBUSB_ERROR_NOT_FOUND; } @@ -198,41 +172,41 @@ error_unload: static int usbdk_init(struct libusb_context *ctx) { - int r; + SC_HANDLE managerHandle; + SC_HANDLE serviceHandle; - if (++concurrent_usage == 0) { // First init? - r = load_usbdk_helper_dll(ctx); - if (r) - goto init_exit; - - init_polling(); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - exit_polling(); - windows_common_exit(); - unload_usbdk_helper_dll(); + managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (managerHandle == NULL) { + usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0)); + return LIBUSB_ERROR_OTHER; } - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. + serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ); + CloseServiceHandle(managerHandle); - return r; + if (serviceHandle == NULL) { + if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) + usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; + } + + CloseServiceHandle(serviceHandle); + + return load_usbdk_helper_dll(ctx); +} + +static void usbdk_exit(struct libusb_context *ctx) +{ + UNUSED(ctx); + unload_usbdk_helper_dll(); } static int usbdk_get_session_id_for_device(struct libusb_context *ctx, PUSB_DK_DEVICE_ID id, unsigned long *session_id) { - char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; + char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID) + 1]; - if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { + if (snprintf(dev_identity, sizeof(dev_identity), "%S%S", id->DeviceID, id->InstanceID) == -1) { usbi_warn(ctx, "cannot form device identity", id->DeviceID); return LIBUSB_ERROR_NOT_SUPPORTED; } @@ -296,11 +270,11 @@ static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) dev->port_number = (uint8_t)info->Port; dev->parent_dev = NULL; - //Addresses in libusb are 1-based + // Addresses in libusb are 1-based dev->device_address = (uint8_t)(info->Port + 1); dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; - dev->device_descriptor = info->DeviceDescriptor; + memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE); switch (info->Speed) { case LowSpeed: @@ -330,7 +304,7 @@ static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_d ULONG dev_number; PUSB_DK_DEVICE_INFO devices; - if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) + if (!usbdk_helper.GetDevicesList(&devices, &dev_number)) return LIBUSB_ERROR_OTHER; for (i = 0; i < dev_number; i++) { @@ -371,26 +345,16 @@ func_exit: return r; } -static void usbdk_exit(void) -{ - if (--concurrent_usage < 0) { - windows_common_exit(); - exit_polling(); - unload_usbdk_helper_dll(); - } -} - -static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) +static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev); memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; return LIBUSB_SUCCESS; } -static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev); PUSB_CONFIGURATION_DESCRIPTOR config_header; @@ -403,15 +367,31 @@ static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config size = min(config_header->wTotalLength, len); memcpy(buffer, config_header, size); - *host_endian = 0; - return (int)size; } -static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) +static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) +{ + struct usbdk_device_priv *priv = _usbdk_device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = priv->config_descriptors[index]; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = (unsigned char *)priv->config_descriptors[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + +static int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) { return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, - buffer, len, host_endian); + buffer, len); } static int usbdk_open(struct libusb_device_handle *dev_handle) @@ -424,6 +404,8 @@ static int usbdk_open(struct libusb_device_handle *dev_handle) return LIBUSB_ERROR_OTHER; } + priv->system_handle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); + return LIBUSB_SUCCESS; } @@ -431,10 +413,8 @@ static void usbdk_close(struct libusb_device_handle *dev_handle) { struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - if (!usbdk_helper.StopRedirect(priv->redirector_handle)) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - usbi_err(ctx, "Redirector shutdown failed"); - } + if (!usbdk_helper.StopRedirect(priv->redirector_handle)) + usbi_err(HANDLE_CTX(dev_handle), "Redirector shutdown failed"); } static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) @@ -460,7 +440,7 @@ static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int if static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { @@ -480,7 +460,7 @@ static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { @@ -493,7 +473,7 @@ static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned ch static int usbdk_reset_device(struct libusb_device_handle *dev_handle) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct libusb_context *ctx = HANDLE_CTX(dev_handle); struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { @@ -504,27 +484,6 @@ static int usbdk_reset_device(struct libusb_device_handle *dev_handle) return LIBUSB_SUCCESS; } -static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - static void usbdk_destroy_device(struct libusb_device *dev) { struct usbdk_device_priv* p = _usbdk_device_priv(dev); @@ -533,12 +492,14 @@ static void usbdk_destroy_device(struct libusb_device *dev) usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); } -void windows_clear_transfer_priv(struct usbi_transfer *itransfer) +static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer) { struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - usbi_free_fd(&transfer_priv->pollable_fd); + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->system_handle = NULL; if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { safe_free(transfer_priv->IsochronousPacketsArray); @@ -551,47 +512,30 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - ULONG Length; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transResult; - HANDLE sysHandle; - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.TransferType = ControlTransferType; - transfer_priv->pollable_fd = INVALID_WINFD; - Length = (ULONG)transfer->length; - if (IS_XFERIN(transfer)) - transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + if (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) + transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transResult) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)Length; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - return LIBUSB_SUCCESS; } @@ -600,12 +544,11 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transferRes; - HANDLE sysHandle; - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; @@ -614,42 +557,29 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) transfer_priv->request.TransferType = BulkTransferType; break; case LIBUSB_TRANSFER_TYPE_INTERRUPT: - transfer_priv->request.TransferType = IntertuptTransferType; + transfer_priv->request.TransferType = InterruptTransferType; break; default: - usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); + usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transferRes) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); - return LIBUSB_SUCCESS; } @@ -658,68 +588,81 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; + struct libusb_context *ctx = TRANSFER_CTX(transfer); + OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped; TransferResult transferRes; int i; - HANDLE sysHandle; - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; + transfer_priv->request.Buffer = (PVOID64)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; transfer_priv->request.TransferType = IsochronousTransferType; transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); - transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; + transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray; if (!transfer_priv->IsochronousPacketsArray) { - usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; + usbi_err(ctx, "Allocation of IsochronousPacketsArray failed"); + return LIBUSB_ERROR_NO_MEM; } transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); - transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; + transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray; if (!transfer_priv->IsochronousResultsArray) { - usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); - free(transfer_priv->IsochronousPacketsArray); - return LIBUSB_ERROR_IO; + usbi_err(ctx, "Allocation of isochronousResultsArray failed"); + return LIBUSB_ERROR_NO_MEM; } for (i = 0; i < transfer->num_iso_packets; i++) transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_NO_MEM; - } - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, overlapped); else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); + transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, overlapped); switch (transferRes) { case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; + windows_force_sync_completion(overlapped, (ULONG)transfer_priv->request.Result.GenResult.BytesTransferred); break; case TransferSuccessAsync: break; case TransferFailure: - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); return LIBUSB_ERROR_IO; } + return LIBUSB_SUCCESS; +} + +static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer, + short events, int (*transfer_fn)(struct usbi_transfer *)) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = TRANSFER_CTX(transfer); + struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd wfd; + int r; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); + return r; + } + + // Use transfer_priv to store data needed for async polling transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); + transfer_priv->system_handle = priv->system_handle; + + r = transfer_fn(itransfer); + if (r != LIBUSB_SUCCESS) { + usbi_remove_pollfd(ctx, wfd.fd); + usbdk_clear_transfer_priv(itransfer); + return r; + } return LIBUSB_SUCCESS; } @@ -727,33 +670,52 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) static int usbdk_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + int (*transfer_fn)(struct usbi_transfer *); + short events; switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: - return usbdk_do_control_transfer(itransfer); + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_control_transfer; + break; case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk - else - return usbdk_do_bulk_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_bulk_transfer; + break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_do_iso_transfer(itransfer); + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = usbdk_do_iso_transfer; + break; default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } + + return usbdk_do_submit_transfer(itransfer, events, transfer_fn); } static int usbdk_abort_transfers(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct libusb_context *ctx = TRANSFER_CTX(transfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; + if (pCancelIoEx != NULL) { + // Use CancelIoEx if available to cancel just a single transfer + if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) { + usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + } else { + if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } } return LIBUSB_SUCCESS; @@ -778,16 +740,16 @@ static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) } } -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) { itransfer->transferred += io_size; return LIBUSB_TRANSFER_COMPLETED; } -struct winfd *windows_get_fd(struct usbi_transfer *transfer) +static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer) { - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - return &transfer_priv->pollable_fd; + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + return transfer_priv->pollable_fd.fd; } static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) @@ -796,30 +758,28 @@ static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) return NO_ERROR; switch (UsbdStatus) { - case USBD_STATUS_STALL_PID: - case USBD_STATUS_ENDPOINT_HALTED: - case USBD_STATUS_BAD_START_FRAME: - return ERROR_GEN_FAILURE; case USBD_STATUS_TIMEOUT: return ERROR_SEM_TIMEOUT; case USBD_STATUS_CANCELED: return ERROR_OPERATION_ABORTED; default: - return ERROR_FUNCTION_FAILED; + return ERROR_GEN_FAILURE; } } -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) +static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size) { - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first - || GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped - struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); + struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; - if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - int i; + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first + || GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + ULONG64 i; for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { - struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; + struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { case STATUS_SUCCESS: @@ -836,70 +796,35 @@ void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd } } - *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; - *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); - } - else { + *io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred; + *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus); + } else { *io_result = GetLastError(); } } -static int usbdk_clock_gettime(int clk_id, struct timespec *tp) -{ - return windows_clock_gettime(clk_id, tp); -} - -const struct usbi_os_backend usbdk_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, +const struct windows_backend usbdk_backend = { usbdk_init, usbdk_exit, - usbdk_get_device_list, - NULL, usbdk_open, usbdk_close, - usbdk_get_device_descriptor, usbdk_get_active_config_descriptor, usbdk_get_config_descriptor, - NULL, - + usbdk_get_config_descriptor_by_value, usbdk_get_configuration, usbdk_set_configuration, usbdk_claim_interface, usbdk_release_interface, - usbdk_set_interface_altsetting, usbdk_clear_halt, usbdk_reset_device, - - NULL, - NULL, - - NULL, // dev_mem_alloc() - NULL, // dev_mem_free() - - usbdk_kernel_driver_active, - usbdk_detach_kernel_driver, - usbdk_attach_kernel_driver, - usbdk_destroy_device, - usbdk_submit_transfer, usbdk_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - usbdk_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct usbdk_device_priv), - 0, - sizeof(struct usbdk_transfer_priv), + usbdk_clear_transfer_priv, + usbdk_copy_transfer_data, + usbdk_get_transfer_fd, + usbdk_get_overlapped_result, }; - -#endif /* USE_USBDK */ diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h similarity index 64% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h index 04a9787f2..77660ae97 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_usbdk.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_usbdk.h @@ -23,56 +23,13 @@ #pragma once -typedef struct tag_USB_DK_DEVICE_ID { - WCHAR DeviceID[MAX_DEVICE_ID_LEN]; - WCHAR InstanceID[MAX_DEVICE_ID_LEN]; -} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; +#include "windows_nt_common.h" -static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) -{ - wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); - wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); -} - -typedef struct tag_USB_DK_DEVICE_INFO { - USB_DK_DEVICE_ID ID; - ULONG64 FilterID; - ULONG64 Port; - ULONG64 Speed; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; -} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; - -typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST { +typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST { USB_DK_DEVICE_ID ID; ULONG64 Index; } USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; -typedef struct tag_USB_DK_ISO_TRANSFER_RESULT { - ULONG64 ActualLength; - ULONG64 TransferResult; -} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; - -typedef struct tag_USB_DK_GEN_TRANSFER_RESULT { - ULONG64 BytesTransferred; - ULONG64 UsbdStatus; // USBD_STATUS code -} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_RESULT { - USB_DK_GEN_TRANSFER_RESULT GenResult; - PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT -} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_REQUEST { - ULONG64 EndpointAddress; - PVOID64 Buffer; - ULONG64 BufferLength; - ULONG64 TransferType; - ULONG64 IsochronousPacketsArraySize; - PVOID64 IsochronousPacketsArray; - - USB_DK_TRANSFER_RESULT Result; -} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; - typedef enum { TransferFailure = 0, TransferSuccess, @@ -90,7 +47,7 @@ typedef enum { typedef enum { ControlTransferType, BulkTransferType, - IntertuptTransferType, + InterruptTransferType, IsochronousTransferType } USB_DK_TRANSFER_TYPE; diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c new file mode 100644 index 000000000..ce1b55cd6 --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.c @@ -0,0 +1,3009 @@ +/* + * windows backend for libusb 1.0 + * Copyright © 2009-2012 Pete Batard + * Copyright © 2016-2018 Chris Dickens + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software + * Hash table functions adapted from glibc, by Ulrich Drepper et al. + * Major code testing contribution by Xiaofan Chen + * + * This 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 2.1 of the License, or (at your option) any later version. + * + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libusbi.h" +#include "windows_common.h" +#include "windows_nt_common.h" +#include "windows_winusb.h" + +// Unfuckup the 'inferface' keyword +#undef interface + +#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE)) + +// The 2 macros below are used in conjunction with safe loops. +#define LOOP_CHECK(fcall) \ + { \ + r = fcall; \ + if (r != LIBUSB_SUCCESS) \ + continue; \ + } +#define LOOP_BREAK(err) \ + { \ + r = err; \ + continue; \ + } + +// WinUSB-like API prototypes +static int winusbx_init(struct libusb_context *ctx); +static void winusbx_exit(void); +static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); +static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); +static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); +static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); +static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); +static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); +// Composite API prototypes +static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); +static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); +static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); +static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); +static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); +static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); +static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer); +static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer); +static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); +static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); + +static usbi_mutex_t autoclaim_lock; + +// API globals +static HMODULE WinUSBX_handle = NULL; +static struct winusb_interface WinUSBX[SUB_API_MAX]; +#define CHECK_WINUSBX_AVAILABLE(sub_api) \ + do { \ + if (sub_api == SUB_API_NOTSET) \ + sub_api = priv->sub_api; \ + if (!WinUSBX[sub_api].initialized) \ + return LIBUSB_ERROR_ACCESS; \ + } while (0) + +static bool api_hid_available = false; +#define CHECK_HID_AVAILABLE \ + do { \ + if (!api_hid_available) \ + return LIBUSB_ERROR_ACCESS; \ + } while (0) + +#if defined(ENABLE_LOGGING) +static const char *guid_to_string(const GUID *guid) +{ + static char guid_string[MAX_GUID_STRING_LENGTH]; + + if (guid == NULL) + return ""; + + sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + (unsigned int)guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); + + return guid_string; +} +#endif + +/* + * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. + * Return an allocated sanitized string or NULL on error. + */ +static char *sanitize_path(const char *path) +{ + const char root_prefix[] = {'\\', '\\', '.', '\\'}; + size_t j, size; + char *ret_path; + size_t add_root = 0; + + if (path == NULL) + return NULL; + + size = strlen(path) + 1; + + // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. + if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) + || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { + add_root = sizeof(root_prefix); + size += add_root; + } + + ret_path = malloc(size); + if (ret_path == NULL) + return NULL; + + strcpy(&ret_path[add_root], path); + + // Ensure consistency with root prefix + memcpy(ret_path, root_prefix, sizeof(root_prefix)); + + // Same goes for '\' and '#' after the root prefix. Ensure '#' is used + for (j = sizeof(root_prefix); j < size; j++) { + ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too + if (ret_path[j] == '\\') + ret_path[j] = '#'; + } + + return ret_path; +} + +/* + * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions + */ +static BOOL init_dlls(void) +{ + DLL_GET_HANDLE(Cfgmgr32); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); + DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); + + // Prefixed to avoid conflict with header files + DLL_GET_HANDLE(AdvAPI32); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); + DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); + + DLL_GET_HANDLE(OLE32); + DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE); + + DLL_GET_HANDLE(SetupAPI); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); + DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); + + return TRUE; +} + +static void exit_dlls(void) +{ + DLL_FREE_HANDLE(Cfgmgr32); + DLL_FREE_HANDLE(AdvAPI32); + DLL_FREE_HANDLE(OLE32); + DLL_FREE_HANDLE(SetupAPI); +} + +/* + * enumerate interfaces for the whole USB class + * + * Parameters: + * dev_info: a pointer to a dev_info list + * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) + * enumerator: the generic USB class for which to retrieve interface details + * index: zero based index of the interface in the device info list + * + * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA + * structure returned and call this function repeatedly using the same guid (with an + * incremented index starting at zero) until all interfaces have been returned. + */ +static bool get_devinfo_data(struct libusb_context *ctx, + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *enumerator, unsigned _index) +{ + if (_index == 0) { + *dev_info = pSetupDiGetClassDevsA(NULL, enumerator, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); + if (*dev_info == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not obtain device info set for PnP enumerator '%s': %s", + enumerator, windows_error_str(0)); + return false; + } + } + + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "could not obtain device info data for PnP enumerator '%s' index %u: %s", + enumerator, _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return false; + } + return true; +} + +/* + * enumerate interfaces for a specific GUID + * + * Parameters: + * dev_info: a pointer to a dev_info list + * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) + * guid: the GUID for which to retrieve interface details + * index: zero based index of the interface in the device info list + * + * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA + * structure returned and call this function repeatedly using the same guid (with an + * incremented index starting at zero) until all interfaces have been returned. + */ +static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info, + PSP_DEVINFO_DATA dev_info_data, LPCGUID guid, DWORD *_index, char **dev_interface_path) +{ + SP_DEVICE_INTERFACE_DATA dev_interface_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details; + DWORD size; + + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + for (;;) { + if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain device info data for %s index %u: %s", + guid_to_string(guid), *_index, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + // No more devices + return LIBUSB_SUCCESS; + } + + // Always advance the index for the next iteration + (*_index)++; + + if (pSetupDiEnumDeviceInterfaces(dev_info, dev_info_data, guid, 0, &dev_interface_data)) + break; + + if (GetLastError() != ERROR_NO_MORE_ITEMS) { + usbi_err(ctx, "Could not obtain interface data for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + + // Device does not have an interface matching this GUID, skip + } + + // Read interface data (dummy + actual) to access the device path + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { + // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + usbi_err(ctx, "could not access interface data (dummy) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + return LIBUSB_ERROR_OTHER; + } + } else { + usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong"); + return LIBUSB_ERROR_OTHER; + } + + dev_interface_details = malloc(size); + if (dev_interface_details == NULL) { + usbi_err(ctx, "could not allocate interface data for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; + } + + dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data, + dev_interface_details, size, NULL, NULL)) { + usbi_err(ctx, "could not access interface data (actual) for %s devInst %X: %s", + guid_to_string(guid), dev_info_data->DevInst, windows_error_str(0)); + free(dev_interface_details); + return LIBUSB_ERROR_OTHER; + } + + *dev_interface_path = sanitize_path(dev_interface_details->DevicePath); + free(dev_interface_details); + + if (*dev_interface_path == NULL) { + usbi_err(ctx, "could not allocate interface path for %s devInst %X", + guid_to_string(guid), dev_info_data->DevInst); + return LIBUSB_ERROR_NO_MEM; + } + + return LIBUSB_SUCCESS; +} + +/* For libusb0 filter */ +static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, + HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) +{ + SP_DEVICE_INTERFACE_DATA dev_interface_data; + SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; + DWORD size; + + if (_index == 0) + *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); + + if (dev_info_data != NULL) { + dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); + if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "Could not obtain device info data for index %u: %s", + _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; + } + } + + dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + usbi_err(ctx, "Could not obtain interface data for index %u: %s", + _index, windows_error_str(0)); + + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; + } + + // Read interface data (dummy + actual) to access the device path + if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { + // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", + _index, windows_error_str(0)); + goto err_exit; + } + } else { + usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); + goto err_exit; + } + + dev_interface_details = calloc(1, size); + if (dev_interface_details == NULL) { + usbi_err(ctx, "could not allocate interface data for index %u.", _index); + goto err_exit; + } + + dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) + usbi_err(ctx, "could not access interface data (actual) for index %u: %s", + _index, windows_error_str(0)); + + // [trobinso] lookup the libusb0 symbolic index. + if (dev_interface_details) { + HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); + if (hkey_device_interface != INVALID_HANDLE_VALUE) { + DWORD libusb0_symboliclink_index = 0; + DWORD value_length = sizeof(DWORD); + DWORD value_type = 0; + LONG status; + + status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, + (LPBYTE)&libusb0_symboliclink_index, &value_length); + if (status == ERROR_SUCCESS) { + if (libusb0_symboliclink_index < 256) { + // libusb0.sys is connected to this device instance. + // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. + sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); + usbi_dbg("assigned libusb0 symbolic link %s", filter_path); + } else { + // libusb0.sys was connected to this device instance at one time; but not anymore. + } + } + pRegCloseKey(hkey_device_interface); + } + } + + return dev_interface_details; + +err_exit: + pSetupDiDestroyDeviceInfoList(*dev_info); + *dev_info = INVALID_HANDLE_VALUE; + return NULL; +} + +/* + * Returns the first known ancestor of a device + */ +static struct libusb_device *get_ancestor(struct libusb_context *ctx, + DEVINST devinst, PDEVINST _parent_devinst) +{ + struct libusb_device *dev = NULL; + DEVINST parent_devinst; + + while (dev == NULL) { + if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) + break; + devinst = parent_devinst; + dev = usbi_get_device_by_session_id(ctx, (unsigned long)devinst); + } + + if ((dev != NULL) && (_parent_devinst != NULL)) + *_parent_devinst = devinst; + + return dev; +} + +/* + * Determine which interface the given endpoint address belongs to + */ +static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep) +{ + const struct libusb_interface *intf; + const struct libusb_interface_descriptor *intf_desc; + int i, j, k; + + for (i = 0; i < conf_desc->bNumInterfaces; i++) { + intf = &conf_desc->interface[i]; + for (j = 0; j < intf->num_altsetting; j++) { + intf_desc = &intf->altsetting[j]; + for (k = 0; k < intf_desc->bNumEndpoints; k++) { + if (intf_desc->endpoint[k].bEndpointAddress == ep) { + usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i); + return intf_desc->bInterfaceNumber; + } + } + } + } + + usbi_dbg("endpoint %02X not found on any interface", ep); + return LIBUSB_ERROR_NOT_FOUND; +} + +/* + * Populate the endpoints addresses of the device_priv interface helper structs + */ +static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + int i, r; + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct libusb_config_descriptor *conf_desc; + const struct libusb_interface_descriptor *if_desc; + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + + r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); + if (r != LIBUSB_SUCCESS) { + usbi_warn(ctx, "could not read config descriptor: error %d", r); + return r; + } + + if_desc = &conf_desc->interface[iface].altsetting[altsetting]; + safe_free(priv->usb_interface[iface].endpoint); + + if (if_desc->bNumEndpoints == 0) { + usbi_dbg("no endpoints found for interface %d", iface); + libusb_free_config_descriptor(conf_desc); + return LIBUSB_SUCCESS; + } + + priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); + if (priv->usb_interface[iface].endpoint == NULL) { + libusb_free_config_descriptor(conf_desc); + return LIBUSB_ERROR_NO_MEM; + } + + priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; + for (i = 0; i < if_desc->bNumEndpoints; i++) { + priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; + usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); + } + libusb_free_config_descriptor(conf_desc); + + // Extra init may be required to configure endpoints + if (priv->apib->configure_endpoints) + r = priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); + + return r; +} + +// Lookup for a match in the list of API driver names +// return -1 if not found, driver match number otherwise +static int get_sub_api(char *driver, int api) +{ + int i; + const char sep_str[2] = {LIST_SEPARATOR, 0}; + char *tok, *tmp_str; + size_t len = strlen(driver); + + if (len == 0) + return SUB_API_NOTSET; + + tmp_str = _strdup(driver); + if (tmp_str == NULL) + return SUB_API_NOTSET; + + tok = strtok(tmp_str, sep_str); + while (tok != NULL) { + for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { + if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { + free(tmp_str); + return i; + } + } + tok = strtok(NULL, sep_str); + } + + free(tmp_str); + return SUB_API_NOTSET; +} + +/* + * auto-claiming and auto-release helper functions + */ +static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) +{ + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv( + transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = *interface_number; + int r = LIBUSB_SUCCESS; + + switch (api_type) { + case USB_API_WINUSBX: + case USB_API_HID: + break; + default: + return LIBUSB_ERROR_INVALID_PARAM; + } + + usbi_mutex_lock(&autoclaim_lock); + if (current_interface < 0) { // No serviceable interface was found + for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { + // Must claim an interface of the same API type + if ((priv->usb_interface[current_interface].apib->id == api_type) + && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { + usbi_dbg("auto-claimed interface %d for control request", current_interface); + if (handle_priv->autoclaim_count[current_interface] != 0) + usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); + handle_priv->autoclaim_count[current_interface]++; + break; + } + } + if (current_interface == USB_MAXINTERFACES) { + usbi_err(ctx, "could not auto-claim any interface"); + r = LIBUSB_ERROR_NOT_FOUND; + } + } else { + // If we have a valid interface that was autoclaimed, we must increment + // its autoclaim count so that we can prevent an early release. + if (handle_priv->autoclaim_count[current_interface] != 0) + handle_priv->autoclaim_count[current_interface]++; + } + usbi_mutex_unlock(&autoclaim_lock); + + *interface_number = current_interface; + return r; +} + +static void auto_release(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + libusb_device_handle *dev_handle = transfer->dev_handle; + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + int r; + + usbi_mutex_lock(&autoclaim_lock); + if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) { + handle_priv->autoclaim_count[transfer_priv->interface_number]--; + if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { + r = libusb_release_interface(dev_handle, transfer_priv->interface_number); + if (r == LIBUSB_SUCCESS) + usbi_dbg("auto-released interface %d", transfer_priv->interface_number); + else + usbi_dbg("failed to auto-release interface %d (%s)", + transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); + } + } + usbi_mutex_unlock(&autoclaim_lock); +} + +/* + * init: libusb backend init function + */ +static int winusb_init(struct libusb_context *ctx) +{ + int i; + + // We need a lock for proper auto-release + usbi_mutex_init(&autoclaim_lock); + + // Load DLL imports + if (!init_dlls()) { + usbi_err(ctx, "could not resolve DLL functions"); + return LIBUSB_ERROR_OTHER; + } + + // Initialize the low level APIs (we don't care about errors at this stage) + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].init && usb_api_backend[i].init(ctx)) + usbi_warn(ctx, "error initializing %s backend", + usb_api_backend[i].designation); + } + + return LIBUSB_SUCCESS; +} + +/* +* exit: libusb backend deinitialization function +*/ +static void winusb_exit(struct libusb_context *ctx) +{ + int i; + + for (i = 0; i < USB_API_MAX; i++) { + if (usb_api_backend[i].exit) + usb_api_backend[i].exit(); + } + + exit_dlls(); + usbi_mutex_destroy(&autoclaim_lock); +} + +/* + * fetch and cache all the config descriptors through I/O + */ +static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev); + struct winusb_device_priv *priv = _device_priv(dev); + DWORD size, ret_size; + uint8_t i; + + USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request + PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request + PUSB_CONFIGURATION_DESCRIPTOR cd_data; + + if (dev->num_configurations == 0) + return; + + priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); + if (priv->config_descriptor == NULL) { + usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id); + return; + } + + for (i = 0; i <= dev->num_configurations; i++) { + safe_free(cd_buf_actual); + + if (i == dev->num_configurations) + break; + + size = sizeof(cd_buf_short); + memset(&cd_buf_short, 0, size); + + cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number; + cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; + cd_buf_short.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_short.req.SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; + cd_buf_short.req.SetupPacket.wIndex = 0; + cd_buf_short.req.SetupPacket.wLength = (USHORT)sizeof(USB_CONFIGURATION_DESCRIPTOR); + + // Dummy call to get the required data size. Initial failures are reported as info rather + // than error as they can occur for non-penalizing situations, such as with some hubs. + // coverity[tainted_data_argument] + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, + &cd_buf_short, size, &ret_size, NULL)) { + usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; + } + + if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { + usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id); + continue; + } + + size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength; + cd_buf_actual = malloc(size); + if (cd_buf_actual == NULL) { + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + continue; + } + + // Actual call + cd_buf_actual->ConnectionIndex = (ULONG)dev->port_number; + cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; + cd_buf_actual->SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; + cd_buf_actual->SetupPacket.wValue = (LIBUSB_DT_CONFIG << 8) | i; + cd_buf_actual->SetupPacket.wIndex = 0; + cd_buf_actual->SetupPacket.wLength = cd_buf_short.desc.wTotalLength; + + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, + cd_buf_actual, size, &ret_size, NULL)) { + usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0)); + continue; + } + + cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); + + if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) { + usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id); + continue; + } + + if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) { + usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id); + continue; + } + + usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)", + i, cd_data->bConfigurationValue, cd_data->wTotalLength); + + // Cache the descriptor + priv->config_descriptor[i] = malloc(cd_data->wTotalLength); + if (priv->config_descriptor[i] != NULL) { + memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); + } else { + usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id); + } + } +} + +/* + * Populate a libusb device structure + */ +static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, + uint8_t port_number, DEVINST devinst) +{ + struct libusb_context *ctx; + struct libusb_device *tmp_dev; + struct winusb_device_priv *priv, *parent_priv; + USB_NODE_CONNECTION_INFORMATION_EX conn_info; + USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; + HANDLE hub_handle; + DWORD size; + uint8_t bus_number, depth; + int r; + + priv = _device_priv(dev); + + // If the device is already initialized, we can stop here + if (priv->initialized) + return LIBUSB_SUCCESS; + + if (parent_dev != NULL) { // Not a HCD root hub + ctx = DEVICE_CTX(dev); + parent_priv = _device_priv(parent_dev); + if (parent_priv->apib->id != USB_API_HUB) { + usbi_warn(ctx, "parent for device '%s' is not a hub", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + // Calculate depth and fetch bus number + bus_number = parent_dev->bus_number; + if (bus_number == 0) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev != parent_dev) { + usbi_err(ctx, "program assertion failed - first ancestor is not parent"); + return LIBUSB_ERROR_NOT_FOUND; + } + libusb_unref_device(tmp_dev); + + for (depth = 1; bus_number == 0; depth++) { + tmp_dev = get_ancestor(ctx, devinst, &devinst); + if (tmp_dev->bus_number != 0) { + bus_number = tmp_dev->bus_number; + depth += _device_priv(tmp_dev)->depth; + } + libusb_unref_device(tmp_dev); + } + } else { + depth = parent_priv->depth + 1; + } + + if (bus_number == 0) { + usbi_err(ctx, "program assertion failed - bus number not found for '%s'", priv->dev_id); + return LIBUSB_ERROR_NOT_FOUND; + } + + dev->bus_number = bus_number; + dev->port_number = port_number; + dev->parent_dev = parent_dev; + priv->depth = depth; + + hub_handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + 0, NULL); + if (hub_handle == INVALID_HANDLE_VALUE) { + usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + + memset(&conn_info, 0, sizeof(conn_info)); + conn_info.ConnectionIndex = (ULONG)port_number; + // coverity[tainted_data_argument] + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, sizeof(conn_info), + &conn_info, sizeof(conn_info), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information for device '%s': %s", + priv->dev_id, windows_error_str(0)); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (conn_info.ConnectionStatus == NoDeviceConnected) { + usbi_err(ctx, "device '%s' is no longer connected!", priv->dev_id); + CloseHandle(hub_handle); + return LIBUSB_ERROR_NO_DEVICE; + } + + memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); + dev->num_configurations = priv->dev_descriptor.bNumConfigurations; + priv->active_config = conn_info.CurrentConfigurationValue; + usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); + + // Cache as many config descriptors as we can + cache_config_descriptors(dev, hub_handle); + + // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 + if (windows_version >= WINDOWS_8) { + conn_info_v2.ConnectionIndex = (ULONG)port_number; + conn_info_v2.Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); + conn_info_v2.SupportedUsbProtocols.Usb300 = 1; + if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, + &conn_info_v2, sizeof(conn_info_v2), &conn_info_v2, sizeof(conn_info_v2), &size, NULL)) { + usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", + priv->dev_id, windows_error_str(0)); + } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { + conn_info.Speed = 3; + } + } + + CloseHandle(hub_handle); + + if (conn_info.DeviceAddress > UINT8_MAX) + usbi_err(ctx, "program assertion failed - device address overflow"); + + dev->device_address = (uint8_t)conn_info.DeviceAddress; + + switch (conn_info.Speed) { + case 0: dev->speed = LIBUSB_SPEED_LOW; break; + case 1: dev->speed = LIBUSB_SPEED_FULL; break; + case 2: dev->speed = LIBUSB_SPEED_HIGH; break; + case 3: dev->speed = LIBUSB_SPEED_SUPER; break; + default: + usbi_warn(ctx, "unknown device speed %u", conn_info.Speed); + break; + } + } + + r = usbi_sanitize_device(dev); + if (r) + return r; + + priv->initialized = true; + + usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", + dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id); + + return LIBUSB_SUCCESS; +} + +static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, + uint8_t bus_number, DEVINST devinst) +{ + struct libusb_device *dev; + struct winusb_device_priv *priv; + unsigned long session_id; + DEVINST child_devinst; + + if (CM_Get_Child(&child_devinst, devinst, 0) != CR_SUCCESS) { + usbi_err(ctx, "could not get child devinst for '%s'", dev_id); + return LIBUSB_ERROR_OTHER; + } + + session_id = (unsigned long)child_devinst; + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id); + return LIBUSB_ERROR_NO_DEVICE; + } + + if (dev->bus_number == 0) { + // Only do this once + usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number); + priv = _device_priv(dev); + dev->bus_number = bus_number; + dev->num_configurations = 1; + priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE; + priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE; + priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB; + priv->dev_descriptor.bNumConfigurations = 1; + priv->active_config = 1; + priv->root_hub = true; + if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &priv->dev_descriptor.idVendor, &priv->dev_descriptor.idProduct) != 2) { + usbi_warn(ctx, "could not infer VID/PID of HCD root hub from '%s'", dev_id); + priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub + priv->dev_descriptor.idProduct = 1; + } + } + + libusb_unref_device(dev); + return LIBUSB_SUCCESS; +} + +// Returns the api type, or 0 if not found/unsupported +static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, + SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) +{ + // Precedence for filter drivers vs driver is in the order of this array + struct driver_lookup lookup[3] = { + {"\0\0", SPDRP_SERVICE, "driver"}, + {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"}, + {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"} + }; + DWORD size, reg_type; + unsigned k, l; + int i, j; + + // Check the service & filter names to know the API we should use + for (k = 0; k < 3; k++) { + if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, + ®_type, (PBYTE)lookup[k].list, MAX_KEY_LENGTH, &size)) { + // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ + if (lookup[k].reg_prop == SPDRP_SERVICE) + // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed + lookup[k].list[strlen(lookup[k].list) + 1] = 0; + + // MULTI_SZ is a pain to work with. Turn it into something much more manageable + // NB: none of the driver names we check against contain LIST_SEPARATOR, + // (currently ';'), so even if an unsuported one does, it's not an issue + for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { + if (lookup[k].list[l] == 0) + lookup[k].list[l] = LIST_SEPARATOR; + } + usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); + } else { + if (GetLastError() != ERROR_INVALID_DATA) + usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); + lookup[k].list[0] = 0; + } + } + + for (i = 2; i < USB_API_MAX; i++) { + for (k = 0; k < 3; k++) { + j = get_sub_api(lookup[k].list, i); + if (j >= 0) { + usbi_dbg("matched %s name against %s", lookup[k].designation, + (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]); + *api = i; + *sub_api = j; + return; + } + } + } +} + +static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path, char *device_id, int api, int sub_api) +{ + struct winusb_device_priv *priv = _device_priv(dev); + int interface_number; + const char *mi_str; + + // Because MI_## are not necessarily in sequential order (some composite + // devices will have only MI_00 & MI_03 for instance), we retrieve the actual + // interface number from the path's MI value + mi_str = strstr(device_id, "MI_"); + if ((mi_str != NULL) && isdigit(mi_str[3]) && isdigit(mi_str[4])) { + interface_number = ((mi_str[3] - '0') * 10) + (mi_str[4] - '0'); + } else { + usbi_warn(ctx, "failure to read interface number for %s, using default value", device_id); + interface_number = 0; + } + + if (interface_number >= USB_MAXINTERFACES) { + usbi_warn(ctx, "interface %d too large - ignoring interface path %s", interface_number, dev_interface_path); + return LIBUSB_ERROR_ACCESS; + } + + if (priv->usb_interface[interface_number].path != NULL) { + if (api == USB_API_HID) { + // HID devices can have multiple collections (COL##) for each MI_## interface + usbi_dbg("interface[%d] already set - ignoring HID collection: %s", + interface_number, device_id); + return LIBUSB_ERROR_ACCESS; + } + // In other cases, just use the latest data + safe_free(priv->usb_interface[interface_number].path); + } + + usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); + priv->usb_interface[interface_number].path = dev_interface_path; + priv->usb_interface[interface_number].apib = &usb_api_backend[api]; + priv->usb_interface[interface_number].sub_api = sub_api; + if ((api == USB_API_HID) && (priv->hid == NULL)) { + priv->hid = calloc(1, sizeof(struct hid_device_priv)); + if (priv->hid == NULL) + return LIBUSB_ERROR_NO_MEM; + } + + return LIBUSB_SUCCESS; +} + +static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, + char *dev_interface_path) +{ + int i; + struct winusb_device_priv *priv = _device_priv(dev); + + if (priv->hid == NULL) { + usbi_err(ctx, "program assertion failed: parent is not HID"); + return LIBUSB_ERROR_NO_DEVICE; + } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { + usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); + return LIBUSB_ERROR_NO_DEVICE; + } + + for (i = 0; i < priv->hid->nb_interfaces; i++) { + if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { + usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); + return LIBUSB_ERROR_ACCESS; + } + } + + priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; + priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; + usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path); + priv->hid->nb_interfaces++; + return LIBUSB_SUCCESS; +} + +/* + * get_device_list: libusb backend device enumeration function + */ +static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) +{ + struct discovered_devs *discdevs; + HDEVINFO *dev_info, dev_info_intf, dev_info_enum; + SP_DEVINFO_DATA dev_info_data; + DWORD _index = 0; + GUID hid_guid; + int r = LIBUSB_SUCCESS; + int api, sub_api; + unsigned int pass, i, j; + char enumerator[16]; + char dev_id[MAX_PATH_LENGTH]; + struct libusb_device *dev, *parent_dev; + struct winusb_device_priv *priv, *parent_priv; + char *dev_interface_path = NULL; + unsigned long session_id; + DWORD size, port_nr, reg_type, install_state; + HKEY key; + WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; + GUID *if_guid; + LONG s; +#define HUB_PASS 0 +#define DEV_PASS 1 +#define HCD_PASS 2 +#define GEN_PASS 3 +#define HID_PASS 4 +#define EXT_PASS 5 + // Keep a list of guids that will be enumerated +#define GUID_SIZE_STEP 8 + const GUID **guid_list, **new_guid_list; + unsigned int guid_size = GUID_SIZE_STEP; + unsigned int nb_guids; + // Keep a list of PnP enumerator strings that are found + char *usb_enumerator[8] = { "USB" }; + unsigned int nb_usb_enumerators = 1; + unsigned int usb_enum_index = 0; + // Keep a list of newly allocated devs to unref +#define UNREF_SIZE_STEP 16 + libusb_device **unref_list, **new_unref_list; + unsigned int unref_size = UNREF_SIZE_STEP; + unsigned int unref_cur = 0; + + // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) + // PASS 2 : (re)enumerate HUBS + // PASS 3 : (re)enumerate generic USB devices (including driverless) + // and list additional USB device interface GUIDs to explore + // PASS 4 : (re)enumerate master USB devices that have a device interface + // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and + // set the device interfaces. + + // Init the GUID table + guid_list = malloc(guid_size * sizeof(void *)); + if (guid_list == NULL) { + usbi_err(ctx, "failed to alloc guid list"); + return LIBUSB_ERROR_NO_MEM; + } + + guid_list[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; + guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; + guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; + guid_list[GEN_PASS] = NULL; + if (api_hid_available) { + HidD_GetHidGuid(&hid_guid); + guid_list[HID_PASS] = &hid_guid; + } else { + guid_list[HID_PASS] = NULL; + } + nb_guids = EXT_PASS; + + unref_list = malloc(unref_size * sizeof(void *)); + if (unref_list == NULL) { + usbi_err(ctx, "failed to alloc unref list"); + free((void *)guid_list); + return LIBUSB_ERROR_NO_MEM; + } + + dev_info_intf = pSetupDiGetClassDevsA(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (dev_info_intf == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "failed to obtain device info list: %s", windows_error_str(0)); + free(unref_list); + free((void *)guid_list); + return LIBUSB_ERROR_OTHER; + } + + for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { +//#define ENUM_DEBUG +#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) + const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"}; + usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass])); +#endif + if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL)) + continue; + + dev_info = (pass != GEN_PASS) ? &dev_info_intf : &dev_info_enum; + + for (i = 0; ; i++) { + // safe loop: free up any (unprotected) dynamic resource + // NB: this is always executed before breaking the loop + safe_free(dev_interface_path); + priv = parent_priv = NULL; + dev = parent_dev = NULL; + + // Safe loop: end of loop conditions + if (r != LIBUSB_SUCCESS) + break; + + if ((pass == HCD_PASS) && (i == UINT8_MAX)) { + usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX); + break; + } + + if (pass != GEN_PASS) { + // Except for GEN, all passes deal with device interfaces + r = get_interface_details(ctx, *dev_info, &dev_info_data, guid_list[pass], &_index, &dev_interface_path); + if ((r != LIBUSB_SUCCESS) || (dev_interface_path == NULL)) { + _index = 0; + break; + } + } else { + // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are + // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". + // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" + // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" + for (; usb_enum_index < nb_usb_enumerators; usb_enum_index++) { + if (get_devinfo_data(ctx, dev_info, &dev_info_data, usb_enumerator[usb_enum_index], i)) + break; + i = 0; + } + if (usb_enum_index == nb_usb_enumerators) + break; + } + + // Read the Device ID path + if (!pSetupDiGetDeviceInstanceIdA(*dev_info, &dev_info_data, dev_id, sizeof(dev_id), NULL)) { + usbi_warn(ctx, "could not read the device instance ID for devInst %X, skipping", + dev_info_data.DevInst); + continue; + } + +#ifdef ENUM_DEBUG + usbi_dbg("PRO: %s", dev_id); +#endif + + // Set API to use or get additional data from generic pass + api = USB_API_UNSUPPORTED; + sub_api = SUB_API_NOTSET; + switch (pass) { + case HCD_PASS: + break; + case HUB_PASS: + api = USB_API_HUB; + // Fetch the PnP enumerator class for this hub + // This will allow us to enumerate all classes during the GEN pass + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, + NULL, (PBYTE)enumerator, sizeof(enumerator), NULL)) { + usbi_err(ctx, "could not read enumerator string for device '%s': %s", dev_id, windows_error_str(0)); + LOOP_BREAK(LIBUSB_ERROR_OTHER); + } + for (j = 0; j < nb_usb_enumerators; j++) { + if (strcmp(usb_enumerator[j], enumerator) == 0) + break; + } + if (j == nb_usb_enumerators) { + usbi_dbg("found new PnP enumerator string '%s'", enumerator); + if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) { + usb_enumerator[nb_usb_enumerators] = _strdup(enumerator); + if (usb_enumerator[nb_usb_enumerators] != NULL) { + nb_usb_enumerators++; + } else { + usbi_err(ctx, "could not allocate enumerator string '%s'", enumerator); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + } else { + usbi_warn(ctx, "too many enumerator strings, some devices may not be accessible"); + } + } + break; + case GEN_PASS: + // We use the GEN pass to detect driverless devices... + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_DRIVER, + NULL, NULL, 0, NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { + usbi_info(ctx, "The following device has no driver: '%s'", dev_id); + usbi_info(ctx, "libusb will not be able to access it"); + } + // ...and to add the additional device interface GUIDs + key = pSetupDiOpenDevRegKey(*dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + if (key == INVALID_HANDLE_VALUE) + break; + // Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order + size = sizeof(guid_string_w); + s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + if (s == ERROR_FILE_NOT_FOUND) + s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, ®_type, + (LPBYTE)guid_string_w, &size); + pRegCloseKey(key); + if ((s == ERROR_SUCCESS) && + (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) || + ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) { + if (nb_guids == guid_size) { + new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *)); + if (new_guid_list == NULL) { + usbi_err(ctx, "failed to realloc guid list"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + guid_list = new_guid_list; + guid_size += GUID_SIZE_STEP; + } + if_guid = malloc(sizeof(*if_guid)); + if (if_guid == NULL) { + usbi_err(ctx, "failed to alloc if_guid"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + if (pIIDFromString(guid_string_w, if_guid) != 0) { + usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id); + free(if_guid); + } else { + // Check if we've already seen this GUID + for (j = EXT_PASS; j < nb_guids; j++) { + if (memcmp(guid_list[j], if_guid, sizeof(*if_guid)) == 0) + break; + } + if (j == nb_guids) { + usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); + guid_list[nb_guids++] = if_guid; + } else { + // Duplicate, ignore + free(if_guid); + } + } + } else if (s == ERROR_SUCCESS) { + usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id); + } + break; + case HID_PASS: + api = USB_API_HID; + break; + default: + // Get the API type (after checking that the driver installation is OK) + if ((!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_INSTALL_STATE, + NULL, (PBYTE)&install_state, sizeof(install_state), &size)) || (size != sizeof(install_state))) { + usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", + dev_id, windows_error_str(0)); + } else if (install_state != 0) { + usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", + dev_id, (unsigned int)install_state); + continue; + } + get_api_type(ctx, dev_info, &dev_info_data, &api, &sub_api); + break; + } + + // Find parent device (for the passes that need it) + if (pass >= GEN_PASS) { + parent_dev = get_ancestor(ctx, dev_info_data.DevInst, NULL); + if (parent_dev == NULL) { + // Root hubs will not have a parent + dev = usbi_get_device_by_session_id(ctx, (unsigned long)dev_info_data.DevInst); + if (dev != NULL) { + priv = _device_priv(dev); + if (priv->root_hub) + goto track_unref; + libusb_unref_device(dev); + } + + usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id); + continue; + } + + parent_priv = _device_priv(parent_dev); + // virtual USB devices are also listed during GEN - don't process these yet + if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { + libusb_unref_device(parent_dev); + continue; + } + } + + // Create new or match existing device, using the devInst as session id + if ((pass <= GEN_PASS) && (pass != HCD_PASS)) { // For subsequent passes, we'll lookup the parent + // These are the passes that create "new" devices + session_id = (unsigned long)dev_info_data.DevInst; + dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev == NULL) { + alloc_device: + usbi_dbg("allocating new device for session [%lX]", session_id); + dev = usbi_alloc_device(ctx, session_id); + if (dev == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + + priv = winusb_device_priv_init(dev); + priv->dev_id = _strdup(dev_id); + if (priv->dev_id == NULL) { + libusb_unref_device(dev); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + } else { + usbi_dbg("found existing device for session [%lX]", session_id); + + priv = _device_priv(dev); + if (strcmp(priv->dev_id, dev_id) != 0) { + usbi_dbg("device instance ID for session [%lX] changed", session_id); + usbi_disconnect_device(dev); + libusb_unref_device(dev); + goto alloc_device; + } + } + + track_unref: + // Keep track of devices that need unref + if (unref_cur == unref_size) { + new_unref_list = realloc(unref_list, (unref_size + UNREF_SIZE_STEP) * sizeof(void *)); + if (new_unref_list == NULL) { + usbi_err(ctx, "could not realloc list for unref - aborting"); + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + } + unref_list = new_unref_list; + unref_size += UNREF_SIZE_STEP; + } + unref_list[unref_cur++] = dev; + } + + // Setup device + switch (pass) { + case HUB_PASS: + case DEV_PASS: + // If the device has already been setup, don't do it again + if (priv->path != NULL) + break; + // Take care of API initialization + priv->path = dev_interface_path; + dev_interface_path = NULL; + priv->apib = &usb_api_backend[api]; + priv->sub_api = sub_api; + switch (api) { + case USB_API_COMPOSITE: + case USB_API_HUB: + break; + case USB_API_HID: + priv->hid = calloc(1, sizeof(struct hid_device_priv)); + if (priv->hid == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + break; + default: + // For other devices, the first interface is the same as the device + priv->usb_interface[0].path = _strdup(priv->path); + if (priv->usb_interface[0].path == NULL) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + // The following is needed if we want API calls to work for both simple + // and composite devices. + for (j = 0; j < USB_MAXINTERFACES; j++) + priv->usb_interface[j].apib = &usb_api_backend[api]; + break; + } + break; + case HCD_PASS: + r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); + break; + case GEN_PASS: + // The SPDRP_ADDRESS for USB devices is the device port number on the hub + port_nr = 0; + if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS, + NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr))) + usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0)); + r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst); + if (r == LIBUSB_SUCCESS) { + // Append device to the list of discovered devices + discdevs = discovered_devs_append(*_discdevs, dev); + if (!discdevs) + LOOP_BREAK(LIBUSB_ERROR_NO_MEM); + + *_discdevs = discdevs; + } else if (r == LIBUSB_ERROR_NO_DEVICE) { + // This can occur if the device was disconnected but Windows hasn't + // refreshed its enumeration yet - in that case, we ignore the device + r = LIBUSB_SUCCESS; + } + break; + default: // HID_PASS and later + if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { + if (parent_priv->apib->id == USB_API_HID) { + usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); + r = set_hid_interface(ctx, parent_dev, dev_interface_path); + } else { + usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); + r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api); + } + switch (r) { + case LIBUSB_SUCCESS: + dev_interface_path = NULL; + break; + case LIBUSB_ERROR_ACCESS: + // interface has already been set => make sure dev_interface_path is freed then + r = LIBUSB_SUCCESS; + break; + default: + LOOP_BREAK(r); + break; + } + } + libusb_unref_device(parent_dev); + break; + } + } + } + + pSetupDiDestroyDeviceInfoList(dev_info_intf); + + // Free any additional GUIDs + for (pass = EXT_PASS; pass < nb_guids; pass++) + free((void *)guid_list[pass]); + free((void *)guid_list); + + // Free any PnP enumerator strings + for (i = 1; i < nb_usb_enumerators; i++) + free(usb_enumerator[i]); + + // Unref newly allocated devs + for (i = 0; i < unref_cur; i++) + libusb_unref_device(unref_list[i]); + free(unref_list); + + return r; +} + +static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer) +{ + struct winusb_device_priv *priv = _device_priv(dev); + + memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); + return LIBUSB_SUCCESS; +} + +static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len) +{ + struct winusb_device_priv *priv = _device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + size_t size; + + // config index is zero based + if (config_index >= dev->num_configurations) + return LIBUSB_ERROR_INVALID_PARAM; + + if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) + return LIBUSB_ERROR_NOT_FOUND; + + config_header = priv->config_descriptor[config_index]; + + size = MIN(config_header->wTotalLength, len); + memcpy(buffer, priv->config_descriptor[config_index], size); + return (int)size; +} + +static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, + unsigned char **buffer) +{ + struct winusb_device_priv *priv = _device_priv(dev); + PUSB_CONFIGURATION_DESCRIPTOR config_header; + uint8_t index; + + if (priv->config_descriptor == NULL) + return LIBUSB_ERROR_NOT_FOUND; + + for (index = 0; index < dev->num_configurations; index++) { + config_header = priv->config_descriptor[index]; + if (config_header == NULL) + continue; + if (config_header->bConfigurationValue == bConfigurationValue) { + *buffer = (unsigned char *)priv->config_descriptor[index]; + return (int)config_header->wTotalLength; + } + } + + return LIBUSB_ERROR_NOT_FOUND; +} + +/* + * return the cached copy of the active config descriptor + */ +static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len) +{ + struct winusb_device_priv *priv = _device_priv(dev); + unsigned char *config_desc; + int r; + + if (priv->active_config == 0) + return LIBUSB_ERROR_NOT_FOUND; + + r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc); + if (r < 0) + return r; + + len = MIN((size_t)r, len); + memcpy(buffer, config_desc, len); + return (int)len; +} + +static int winusb_open(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, open); + + return priv->apib->open(SUB_API_NOTSET, dev_handle); +} + +static void winusb_close(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + if (priv->apib->close) + priv->apib->close(SUB_API_NOTSET, dev_handle); +} + +static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + if (priv->active_config == 0) { + *config = 0; + return LIBUSB_ERROR_NOT_FOUND; + } + + *config = priv->active_config; + return LIBUSB_SUCCESS; +} + +/* + * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver + * does not currently expose a service that allows higher-level drivers to set + * the configuration." + */ +static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r = LIBUSB_SUCCESS; + + if (config >= USB_MAXCONFIG) + return LIBUSB_ERROR_INVALID_PARAM; + + r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, + LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, + 0, NULL, 0, 1000); + + if (r == LIBUSB_SUCCESS) + priv->active_config = (uint8_t)config; + + return r; +} + +static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, claim_interface); + + safe_free(priv->usb_interface[iface].endpoint); + priv->usb_interface[iface].nb_endpoints = 0; + + r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); + + if (r == LIBUSB_SUCCESS) + r = windows_assign_endpoints(dev_handle, iface, 0); + + return r; +} + +static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + + CHECK_SUPPORTED_API(priv->apib, set_interface_altsetting); + + safe_free(priv->usb_interface[iface].endpoint); + priv->usb_interface[iface].nb_endpoints = 0; + + r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); + + if (r == LIBUSB_SUCCESS) + r = windows_assign_endpoints(dev_handle, iface, altsetting); + + return r; +} + +static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, release_interface); + + return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); +} + +static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, clear_halt); + + return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); +} + +static int winusb_reset_device(struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, reset_device); + + return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); +} + +static void winusb_destroy_device(struct libusb_device *dev) +{ + winusb_device_priv_release(dev); +} + +static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + + usbi_close(transfer_priv->pollable_fd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + transfer_priv->handle = NULL; + safe_free(transfer_priv->hid_buffer); + safe_free(transfer_priv->iso_context); + + // When auto claim is in use, attempt to release the auto-claimed interface + auto_release(itransfer); +} + +static int do_submit_transfer(struct usbi_transfer *itransfer, short events, + int (*transfer_fn)(int, struct usbi_transfer *)) +{ + struct libusb_context *ctx = ITRANSFER_CTX(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd wfd; + int r; + + wfd = usbi_create_fd(); + if (wfd.fd < 0) + return LIBUSB_ERROR_NO_MEM; + + r = usbi_add_pollfd(ctx, wfd.fd, events); + if (r) { + usbi_close(wfd.fd); + return r; + } + + // Use transfer_priv to store data needed for async polling + transfer_priv->pollable_fd = wfd; + + r = transfer_fn(SUB_API_NOTSET, itransfer); + + if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) { + usbi_remove_pollfd(ctx, wfd.fd); + usbi_close(wfd.fd); + transfer_priv->pollable_fd = INVALID_WINFD; + } + + return r; +} + +static int winusb_submit_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int (*transfer_fn)(int, struct usbi_transfer *); + short events; + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_control_transfer; + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) + return LIBUSB_ERROR_NOT_SUPPORTED; + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_bulk_transfer; + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + events = IS_XFERIN(transfer) ? POLLIN : POLLOUT; + transfer_fn = priv->apib->submit_iso_transfer; + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return LIBUSB_ERROR_NOT_SUPPORTED; + default: + usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } + + if (transfer_fn == NULL) { + usbi_warn(TRANSFER_CTX(transfer), + "unsupported transfer type %d (unrecognized device driver)", + transfer->type); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + + return do_submit_transfer(itransfer, events, transfer_fn); +} + +static int windows_abort_control(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_control); + + return priv->apib->abort_control(SUB_API_NOTSET, itransfer); +} + +static int windows_abort_transfers(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + + CHECK_SUPPORTED_API(priv->apib, abort_transfers); + + return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); +} + +static int winusb_cancel_transfer(struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: + return windows_abort_control(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + return windows_abort_transfers(itransfer); + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + return LIBUSB_ERROR_NOT_SUPPORTED; + default: + usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); + return LIBUSB_ERROR_INVALID_PARAM; + } +} + +static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); +} + +static int winusb_get_transfer_fd(struct usbi_transfer *itransfer) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + return transfer_priv->pollable_fd.fd; +} + +static void winusb_get_overlapped_result(struct usbi_transfer *itransfer, + DWORD *io_result, DWORD *io_size) +{ + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winfd *pollable_fd = &transfer_priv->pollable_fd; + + if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { + *io_result = NO_ERROR; + *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; + } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) { + // Regular async overlapped + *io_result = NO_ERROR; + } else { + *io_result = GetLastError(); + } +} + +// NB: MSVC6 does not support named initializers. +const struct windows_backend winusb_backend = { + winusb_init, + winusb_exit, + winusb_get_device_list, + winusb_open, + winusb_close, + winusb_get_device_descriptor, + winusb_get_active_config_descriptor, + winusb_get_config_descriptor, + winusb_get_config_descriptor_by_value, + winusb_get_configuration, + winusb_set_configuration, + winusb_claim_interface, + winusb_release_interface, + winusb_set_interface_altsetting, + winusb_clear_halt, + winusb_reset_device, + winusb_destroy_device, + winusb_submit_transfer, + winusb_cancel_transfer, + winusb_clear_transfer_priv, + winusb_copy_transfer_data, + winusb_get_transfer_fd, + winusb_get_overlapped_result, +}; + +/* + * USB API backends + */ + +static const char * const composite_driver_names[] = {"USBCCGP"}; +static const char * const winusbx_driver_names[] = {"libusbK", "libusb0", "WinUSB"}; +static const char * const hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; +const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { + { + USB_API_UNSUPPORTED, + "Unsupported API", + // No supported operations + }, + { + USB_API_HUB, + "HUB API", + // No supported operations + }, + { + USB_API_COMPOSITE, + "Composite API", + composite_driver_names, + ARRAYSIZE(composite_driver_names), + NULL, /* init */ + NULL, /* exit */ + composite_open, + composite_close, + NULL, /* configure_endpoints */ + composite_claim_interface, + composite_set_interface_altsetting, + composite_release_interface, + composite_clear_halt, + composite_reset_device, + composite_submit_bulk_transfer, + composite_submit_iso_transfer, + composite_submit_control_transfer, + composite_abort_control, + composite_abort_transfers, + composite_copy_transfer_data, + }, + { + USB_API_WINUSBX, + "WinUSB-like APIs", + winusbx_driver_names, + ARRAYSIZE(winusbx_driver_names), + winusbx_init, + winusbx_exit, + winusbx_open, + winusbx_close, + winusbx_configure_endpoints, + winusbx_claim_interface, + winusbx_set_interface_altsetting, + winusbx_release_interface, + winusbx_clear_halt, + winusbx_reset_device, + winusbx_submit_bulk_transfer, + winusbx_submit_iso_transfer, + winusbx_submit_control_transfer, + winusbx_abort_control, + winusbx_abort_transfers, + winusbx_copy_transfer_data, + }, + { + USB_API_HID, + "HID API", + // No supported operations + }, +}; + + +/* + * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions + */ +#define WinUSBX_Set(fn) \ + do { \ + if (native_winusb) \ + WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ + else \ + pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ + } while (0) + +static int winusbx_init(struct libusb_context *ctx) +{ + HMODULE h; + bool native_winusb; + int i; + KLIB_VERSION LibK_Version; + LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; + LibK_GetVersion_t pLibK_GetVersion; + + h = LoadLibraryA("libusbK"); + + if (h == NULL) { + usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); + h = LoadLibraryA("WinUSB"); + + if (h == NULL) { + usbi_warn(ctx, "WinUSB DLL is not available either, " + "you will not be able to access devices outside of enumeration"); + return LIBUSB_ERROR_NOT_FOUND; + } + } else { + usbi_dbg("using libusbK DLL for universal access"); + pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); + if (pLibK_GetVersion != NULL) { + pLibK_GetVersion(&LibK_Version); + usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, + LibK_Version.Micro, LibK_Version.Nano); + } + pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); + if (pLibK_GetProcAddress == NULL) { + usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); + FreeLibrary(h); + return LIBUSB_ERROR_NOT_FOUND; + } + } + + native_winusb = (pLibK_GetProcAddress == NULL); + for (i = 0; i < SUB_API_MAX; i++) { + WinUSBX_Set(AbortPipe); + WinUSBX_Set(ControlTransfer); + WinUSBX_Set(FlushPipe); + WinUSBX_Set(Free); + WinUSBX_Set(GetAssociatedInterface); + WinUSBX_Set(Initialize); + WinUSBX_Set(ReadPipe); + if (!native_winusb) + WinUSBX_Set(ResetDevice); + WinUSBX_Set(ResetPipe); + WinUSBX_Set(SetCurrentAlternateSetting); + WinUSBX_Set(SetPipePolicy); + WinUSBX_Set(WritePipe); + WinUSBX_Set(IsoReadPipe); + WinUSBX_Set(IsoWritePipe); + + if (WinUSBX[i].Initialize != NULL) { + WinUSBX[i].initialized = true; + // Assume driver supports CancelIoEx() if it is available + WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); + usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); + } else { + usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); + WinUSBX[i].initialized = false; + } + } + + WinUSBX_handle = h; + return LIBUSB_SUCCESS; +} + +static void winusbx_exit(void) +{ + if (WinUSBX_handle != NULL) { + FreeLibrary(WinUSBX_handle); + WinUSBX_handle = NULL; + + /* Reset the WinUSBX API structures */ + memset(&WinUSBX, 0, sizeof(WinUSBX)); + } +} + +// NB: open and close must ensure that they only handle interface of +// the right API type, as these functions can be called wholesale from +// composite_open(), with interfaces belonging to different APIs +static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + HANDLE file_handle; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // WinUSB requires a separate handle for each interface + for (i = 0; i < USB_MAXINTERFACES; i++) { + if ((priv->usb_interface[i].path != NULL) + && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { + file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + if (file_handle == INVALID_HANDLE_VALUE) { + usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: // The device was disconnected + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_ACCESS_DENIED: + return LIBUSB_ERROR_ACCESS; + default: + return LIBUSB_ERROR_IO; + } + } + handle_priv->interface_handle[i].dev_handle = file_handle; + } + } + return LIBUSB_SUCCESS; +} + +static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE handle; + int i; + + if (sub_api == SUB_API_NOTSET) + sub_api = priv->sub_api; + + if (!WinUSBX[sub_api].initialized) + return; + + if (priv->apib->id == USB_API_COMPOSITE) { + // If this is a composite device, just free and close all WinUSB-like + // interfaces directly (each is independent and not associated with another) + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[i].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } + } + } else { + // If this is a WinUSB device, free all interfaces above interface 0, + // then free and close interface 0 last + for (i = 1; i < USB_MAXINTERFACES; i++) { + handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + } + handle = handle_priv->interface_handle[0].api_handle; + if (HANDLE_VALID(handle)) + WinUSBX[sub_api].Free(handle); + + handle = handle_priv->interface_handle[0].dev_handle; + if (HANDLE_VALID(handle)) + CloseHandle(handle); + } +} + +static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; + UCHAR policy; + ULONG timeout = 0; + uint8_t endpoint_address; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // With handle and enpoints set (in parent), we can setup the default pipe properties + // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx + for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { + endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) + usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); + + if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) + continue; // Other policies don't apply to control endpoint or libusb0 + + policy = false; + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) + usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); + + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) + usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); + + policy = true; + /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: + https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) + usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); + + if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, + AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) + usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); + SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; + HDEVINFO dev_info = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA dev_info_data; + char *dev_path_no_guid = NULL; + char filter_path[] = "\\\\.\\libusb0-0000"; + bool found_filter = false; + HANDLE file_handle, winusb_handle; + DWORD err; + int i; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // If the device is composite, but using the default Windows composite parent driver (usbccgp) + // or if it's the first WinUSB-like interface, we get a handle through Initialize(). + if ((is_using_usbccgp) || (iface == 0)) { + // composite device (independent interfaces) or interface 0 + file_handle = handle_priv->interface_handle[iface].dev_handle; + if (!HANDLE_VALID(file_handle)) + return LIBUSB_ERROR_NOT_FOUND; + + if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + err = GetLastError(); + switch (err) { + case ERROR_BAD_COMMAND: + // The device was disconnected + usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + default: + // it may be that we're using the libusb0 filter driver. + // TODO: can we move this whole business into the K/0 DLL? + for (i = 0; ; i++) { + safe_free(dev_interface_details); + safe_free(dev_path_no_guid); + + dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); + if ((found_filter) || (dev_interface_details == NULL)) + break; + + // ignore GUID part + dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); + if (dev_path_no_guid == NULL) + continue; + + if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { + file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + if (file_handle != INVALID_HANDLE_VALUE) { + if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + // Replace the existing file handle with the working one + CloseHandle(handle_priv->interface_handle[iface].dev_handle); + handle_priv->interface_handle[iface].dev_handle = file_handle; + found_filter = true; + } else { + usbi_err(ctx, "could not initialize filter driver for %s", filter_path); + CloseHandle(file_handle); + } + } else { + usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); + } + } + } + free(dev_interface_details); + if (!found_filter) { + usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); + return LIBUSB_ERROR_ACCESS; + } + } + } + handle_priv->interface_handle[iface].api_handle = winusb_handle; + } else { + // For all other interfaces, use GetAssociatedInterface() + winusb_handle = handle_priv->interface_handle[0].api_handle; + // It is a requirement for multiple interface devices on Windows that, to you + // must first claim the first interface before you claim the others + if (!HANDLE_VALID(winusb_handle)) { + file_handle = handle_priv->interface_handle[0].dev_handle; + if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { + handle_priv->interface_handle[0].api_handle = winusb_handle; + usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface); + } else { + usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + } + if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), + &handle_priv->interface_handle[iface].api_handle)) { + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + switch (GetLastError()) { + case ERROR_NO_MORE_ITEMS: // invalid iface + return LIBUSB_ERROR_NOT_FOUND; + case ERROR_BAD_COMMAND: // The device was disconnected + return LIBUSB_ERROR_NO_DEVICE; + case ERROR_ALREADY_EXISTS: // already claimed + return LIBUSB_ERROR_BUSY; + default: + usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); + return LIBUSB_ERROR_ACCESS; + } + } + } + usbi_dbg("claimed interface %d", iface); + handle_priv->active_interface = iface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + winusb_handle = handle_priv->interface_handle[iface].api_handle; + if (!HANDLE_VALID(winusb_handle)) + return LIBUSB_ERROR_NOT_FOUND; + + WinUSBX[sub_api].Free(winusb_handle); + handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; + + return LIBUSB_SUCCESS; +} + +/* + * Return the first valid interface (of the same API type), for control transfers + */ +static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) +{ + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int i; + + if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { + usbi_dbg("unsupported API ID"); + return -1; + } + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) + && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) + && (priv->usb_interface[i].apib->id == api_id)) + return i; + } + + return -1; +} + +/* + * Lookup interface by endpoint address. -1 if not found + */ +static int interface_by_endpoint(struct winusb_device_priv *priv, + struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address) +{ + int i, j; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) + continue; + if (priv->usb_interface[i].endpoint == NULL) + continue; + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { + if (priv->usb_interface[i].endpoint[j] == endpoint_address) + return i; + } + } + + return -1; +} + +static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer; + ULONG size; + HANDLE winusb_handle; + OVERLAPPED *overlapped; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; + + // Windows places upper limits on the control transfer size + // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx + if (size > MAX_CTRL_BUFFER_LENGTH) + return LIBUSB_ERROR_INVALID_PARAM; + + current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); + if (current_interface < 0) { + if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("will use interface %d", current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + // Sending of set configuration control requests from WinUSB creates issues + if ((LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD) + && (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) { + if (setup->Value != priv->active_config) { + usbi_warn(ctx, "cannot set configuration other than the default one"); + return LIBUSB_ERROR_INVALID_PARAM; + } + windows_force_sync_completion(overlapped, 0); + } else { + if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, size); + } + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + if (altsetting > 255) + return LIBUSB_ERROR_INVALID_PARAM; + + winusb_handle = handle_priv->interface_handle[iface].api_handle; + if (!HANDLE_VALID(winusb_handle)) { + usbi_err(ctx, "interface must be claimed first"); + return LIBUSB_ERROR_NOT_FOUND; + } + + if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) { + usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE winusb_handle; + OVERLAPPED *overlapped; + bool ret; + int current_interface; + int i; + UINT offset; + PKISO_CONTEXT iso_context; + size_t iso_ctx_size; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + if ((sub_api != SUB_API_LIBUSBK) && (sub_api != SUB_API_LIBUSB0)) { + // iso only supported on libusbk-based backends + PRINT_UNSUPPORTED_API(submit_iso_transfer); + return LIBUSB_ERROR_NOT_SUPPORTED; + }; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET)); + transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size); + if (transfer_priv->iso_context == NULL) + return LIBUSB_ERROR_NO_MEM; + + // start ASAP + iso_context->StartFrame = 0; + iso_context->NumberOfPackets = (SHORT)transfer->num_iso_packets; + + // convert the transfer packet lengths to iso_packet offsets + offset = 0; + for (i = 0; i < transfer->num_iso_packets; i++) { + iso_context->IsoPackets[i].offset = offset; + offset += transfer->iso_packet_desc[i].length; + } + + if (IS_XFERIN(transfer)) { + usbi_dbg("reading %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } else { + usbi_dbg("writing %d iso packets", transfer->num_iso_packets); + ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context); + } + + if (!ret) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE winusb_handle; + OVERLAPPED *overlapped; + bool ret; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); + + transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + overlapped = transfer_priv->pollable_fd.overlapped; + + if (IS_XFERIN(transfer)) { + usbi_dbg("reading %d bytes", transfer->length); + ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); + } else { + usbi_dbg("writing %d bytes", transfer->length); + ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped); + } + + if (!ret) { + if (GetLastError() != ERROR_IO_PENDING) { + usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_IO; + } + } else { + windows_force_sync_completion(overlapped, (ULONG)transfer->length); + } + + transfer_priv->interface_number = (uint8_t)current_interface; + + return LIBUSB_SUCCESS; +} + +static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = interface_by_endpoint(priv, handle_priv, endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); + return LIBUSB_ERROR_NOT_FOUND; + } + + usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); + winusb_handle = handle_priv->interface_handle[current_interface].api_handle; + + if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) { + usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +/* + * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed + * through testing as well): + * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel + * the control transfer using CancelIo" + */ +static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer) +{ + // Cancelling of the I/O is done in the parent + return LIBUSB_SUCCESS; +} + +static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + HANDLE handle; + int current_interface; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + current_interface = transfer_priv->interface_number; + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(ctx, "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + usbi_dbg("will use interface %d", current_interface); + + if (WinUSBX[sub_api].CancelIoEx_supported) { + // Try to use CancelIoEx if available to cancel just a single transfer + handle = handle_priv->interface_handle[current_interface].dev_handle; + if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) + return LIBUSB_SUCCESS; + else if (GetLastError() == ERROR_NOT_FOUND) + return LIBUSB_ERROR_NOT_FOUND; + + // Not every driver implements the necessary functionality for CancelIoEx + usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]); + WinUSBX[sub_api].CancelIoEx_supported = false; + } + + handle = handle_priv->interface_handle[current_interface].api_handle; + if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) { + usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NO_DEVICE; + } + + return LIBUSB_SUCCESS; +} + +/* + * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper + * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx): + * "WinUSB does not support host-initiated reset port and cycle port operations" and + * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the + * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is + * cycle the pipes (and even then, the control pipe can not be reset using WinUSB) + */ +// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?) +static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + HANDLE winusb_handle; + int i, j; + + CHECK_WINUSBX_AVAILABLE(sub_api); + + // Reset any available pipe (except control) + for (i = 0; i < USB_MAXINTERFACES; i++) { + winusb_handle = handle_priv->interface_handle[i].api_handle; + if (HANDLE_VALID(winusb_handle)) { + for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { + usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); + if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) + usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + + // FlushPipe seems to fail on OUT pipes + if (IS_EPIN(priv->usb_interface[i].endpoint[j]) + && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) + usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + + if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) + usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", + priv->usb_interface[i].endpoint[j], windows_error_str(0)); + } + } + } + + // libusbK & libusb0 have the ability to issue an actual device reset + if (WinUSBX[sub_api].ResetDevice != NULL) { + winusb_handle = handle_priv->interface_handle[0].api_handle; + if (HANDLE_VALID(winusb_handle)) + WinUSBX[sub_api].ResetDevice(winusb_handle); + } + + return LIBUSB_SUCCESS; +} + +static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + PKISO_CONTEXT iso_context; + int i; + + if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { + CHECK_WINUSBX_AVAILABLE(sub_api); + + // for isochronous, need to copy the individual iso packet actual_lengths and statuses + if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) { + // iso only supported on libusbk-based backends for now + iso_context = transfer_priv->iso_context; + for (i = 0; i < transfer->num_iso_packets; i++) { + transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length; + // TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status + //transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status; + } + } else { + // This should only occur if backend is not set correctly or other backend isoc is partially implemented + PRINT_UNSUPPORTED_API(copy_transfer_data); + return LIBUSB_ERROR_NOT_SUPPORTED; + } + } + + itransfer->transferred += io_size; + return LIBUSB_TRANSFER_COMPLETED; +} + +/* + * Composite API functions + */ +static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r = LIBUSB_ERROR_NOT_FOUND; + uint8_t i; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + switch (priv->usb_interface[i].apib->id) { + case USB_API_WINUSBX: + if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) { + available[priv->usb_interface[i].sub_api] = true; + } + break; + case USB_API_HID: + available[SUB_API_MAX] = true; + break; + default: + break; + } + } + + for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers + if (available[i]) { + r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle); + if (r != LIBUSB_SUCCESS) { + return r; + } + } + } +/* + if (available[SUB_API_MAX]) // HID driver + r = hid_open(SUB_API_NOTSET, dev_handle); +*/ + return r; +} + +static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + uint8_t i; + // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID + bool available[SUB_API_MAX + 1] = { 0 }; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + switch (priv->usb_interface[i].apib->id) { + case USB_API_WINUSBX: + if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) + available[priv->usb_interface[i].sub_api] = true; + break; + case USB_API_HID: + available[SUB_API_MAX] = true; + break; + default: + break; + } + } + + for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers + if (available[i]) + usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); + } +/* + if (available[SUB_API_MAX]) // HID driver + hid_close(SUB_API_NOTSET, dev_handle); +*/ +} + +static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, claim_interface); + + return priv->usb_interface[iface].apib-> + claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); +} + +static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, set_interface_altsetting); + + return priv->usb_interface[iface].apib-> + set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); +} + +static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + + CHECK_SUPPORTED_API(priv->usb_interface[iface].apib, release_interface); + + return priv->usb_interface[iface].apib-> + release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); +} + +static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + struct libusb_config_descriptor *conf_desc; + WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; + int iface, pass, r; + + // Interface shouldn't matter for control, but it does in practice, with Windows' + // restrictions with regards to accessing HID keyboards and mice. Try to target + // a specific interface first, if possible. + switch (LIBUSB_REQ_RECIPIENT(setup->RequestType)) { + case LIBUSB_RECIPIENT_INTERFACE: + iface = setup->Index & 0xFF; + break; + case LIBUSB_RECIPIENT_ENDPOINT: + r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); + if (r == LIBUSB_SUCCESS) { + iface = get_interface_by_endpoint(conf_desc, (setup->Index & 0xFF)); + libusb_free_config_descriptor(conf_desc); + break; + } + // Fall through if not able to determine interface + default: + iface = -1; + break; + } + + // Try and target a specific interface if the control setup indicates such + if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { + usbi_dbg("attempting control transfer targeted to interface %d", iface); + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { + r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); + if (r == LIBUSB_SUCCESS) + return r; + } + } + + // Either not targeted to a specific interface or no luck in doing so. + // Try a 2 pass approach with all interfaces. + for (pass = 0; pass < 2; pass++) { + for (iface = 0; iface < USB_MAXINTERFACES; iface++) { + if ((priv->usb_interface[iface].path != NULL) + && (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) { + if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { + usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); + continue; + } + usbi_dbg("using interface %d", iface); + r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); + // If not supported on this API, it may be supported on another, so don't give up yet!! + if (r == LIBUSB_ERROR_NOT_SUPPORTED) + continue; + return r; + } + } + } + usbi_err(ctx, "no libusb supported interfaces to complete request"); + return LIBUSB_ERROR_NOT_FOUND; +} + +static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_bulk_transfer); + + return priv->usb_interface[current_interface].apib-> + submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, submit_iso_transfer); + + return priv->usb_interface[current_interface].apib-> + submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) +{ + struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); + struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int current_interface; + + current_interface = interface_by_endpoint(priv, handle_priv, endpoint); + if (current_interface < 0) { + usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, clear_halt); + + return priv->usb_interface[current_interface].apib-> + clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); +} + +static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control); + + return priv->usb_interface[current_interface].apib-> + abort_control(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { + usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number"); + return LIBUSB_ERROR_NOT_FOUND; + } + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers); + + return priv->usb_interface[current_interface].apib-> + abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer); +} + +static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) +{ + struct winusb_device_priv *priv = _device_priv(dev_handle->dev); + int r; + uint8_t i; + bool available[SUB_API_MAX]; + + for (i = 0; i < SUB_API_MAX; i++) + available[i] = false; + + for (i = 0; i < USB_MAXINTERFACES; i++) { + if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) + && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) + available[priv->usb_interface[i].sub_api] = true; + } + + for (i = 0; i < SUB_API_MAX; i++) { + if (available[i]) { + r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle); + if (r != LIBUSB_SUCCESS) + return r; + } + } + + return LIBUSB_SUCCESS; +} + +static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) +{ + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); + struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev); + int current_interface = transfer_priv->interface_number; + + CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data); + + return priv->usb_interface[current_interface].apib-> + copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size); +} diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.h b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h similarity index 54% rename from vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.h rename to vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h index b7b9cd919..c1ad4eb9b 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/os/windows_winusb.h @@ -36,15 +36,14 @@ #endif // Missing from MSVC6 setupapi.h -#if !defined(SPDRP_ADDRESS) +#ifndef SPDRP_ADDRESS #define SPDRP_ADDRESS 28 #endif -#if !defined(SPDRP_INSTALL_STATE) +#ifndef SPDRP_INSTALL_STATE #define SPDRP_INSTALL_STATE 34 #endif #define MAX_CTRL_BUFFER_LENGTH 4096 -#define MAX_USB_DEVICES 256 #define MAX_USB_STRING_LENGTH 128 #define MAX_HID_REPORT_SIZE 1024 #define MAX_HID_DESCRIPTOR_SIZE 256 @@ -61,17 +60,17 @@ // http://msdn.microsoft.com/en-us/library/ff545978.aspx // http://msdn.microsoft.com/en-us/library/ff545972.aspx // http://msdn.microsoft.com/en-us/library/ff545982.aspx -#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) -const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} }; +#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER +const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = {0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27}}; #endif -#if !defined(GUID_DEVINTERFACE_USB_DEVICE) -const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} }; +#ifndef GUID_DEVINTERFACE_USB_DEVICE +const GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}}; #endif -#if !defined(GUID_DEVINTERFACE_USB_HUB) -const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} }; +#ifndef GUID_DEVINTERFACE_USB_HUB +const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8}}; #endif -#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER) -const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} }; +#ifndef GUID_DEVINTERFACE_LIBUSB0_FILTER +const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}}; #endif @@ -84,8 +83,6 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8 #define USB_API_WINUSBX 3 #define USB_API_HID 4 #define USB_API_MAX 5 -// The following is used to indicate if the HID or composite extra props have already been set. -#define USB_API_SET (1 << USB_API_MAX) // Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL) // Must have the same values as the KUSB_DRVID enum from libusbk.h @@ -95,15 +92,13 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8 #define SUB_API_WINUSB 2 #define SUB_API_MAX 3 -#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"} - struct windows_usb_api_backend { const uint8_t id; - const char *designation; - const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp" + const char * const designation; + const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp" const uint8_t nb_driver_names; - int (*init)(int sub_api, struct libusb_context *ctx); - int (*exit)(int sub_api); + int (*init)(struct libusb_context *ctx); + void (*exit)(void); int (*open)(int sub_api, struct libusb_device_handle *dev_handle); void (*close)(int sub_api, struct libusb_device_handle *dev_handle); int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface); @@ -123,9 +118,16 @@ struct windows_usb_api_backend { extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; #define PRINT_UNSUPPORTED_API(fname) \ - usbi_dbg("unsupported API call for '" \ - #fname "' (unrecognized device driver)"); \ - return LIBUSB_ERROR_NOT_SUPPORTED; + usbi_dbg("unsupported API call for '%s' " \ + "(unrecognized device driver)", #fname) + +#define CHECK_SUPPORTED_API(apip, fname) \ + do { \ + if ((apip)->fname == NULL) { \ + PRINT_UNSUPPORTED_API(fname); \ + return LIBUSB_ERROR_NOT_SUPPORTED; \ + } \ + } while (0) /* * private structures definition @@ -154,15 +156,16 @@ struct libusb_hid_descriptor { #define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) #define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) +#ifndef CTL_CODE +#define CTL_CODE(DeviceType, Function, Method, Access) \ + (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) +#endif + // The following are used for HID reports IOCTLs -#define HID_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS) -#define HID_BUFFER_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) #define HID_IN_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define HID_OUT_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) #define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) @@ -193,39 +196,20 @@ struct hid_device_priv { uint16_t input_report_size; uint16_t output_report_size; uint16_t feature_report_size; + uint16_t usage; + uint16_t usagePage; WCHAR string[3][MAX_USB_STRING_LENGTH]; uint8_t string_index[3]; // man, prod, ser }; -struct windows_device_priv { - uint8_t depth; // distance to HCD - uint8_t port; // port number on the hub - uint8_t active_config; - struct windows_usb_api_backend const *apib; - char *path; // device interface path - int sub_api; // for WinUSB-like APIs - struct { - char *path; // each interface needs a device interface path, - struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support), - int sub_api; - int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) - uint8_t *endpoint; - bool restricted_functionality; // indicates if the interface functionality is restricted - // by Windows (eg. HID keyboards or mice cannot do R/W) - } usb_interface[USB_MAXINTERFACES]; - struct hid_device_priv *hid; - USB_DEVICE_DESCRIPTOR dev_descriptor; - unsigned char **config_descriptor; // list of pointers to the cached config descriptors -}; - -static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) +static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev) { - return (struct windows_device_priv *)dev->os_priv; + return (struct winusb_device_priv *)dev->os_priv; } -static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev) +static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev) { - struct windows_device_priv *p = _device_priv(dev); + struct winusb_device_priv *p = _device_priv(dev); int i; p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; @@ -238,11 +222,12 @@ static inline struct windows_device_priv *windows_device_priv_init(struct libusb return p; } -static inline void windows_device_priv_release(struct libusb_device *dev) +static inline void winusb_device_priv_release(struct libusb_device *dev) { - struct windows_device_priv *p = _device_priv(dev); + struct winusb_device_priv *p = _device_priv(dev); int i; + free(p->dev_id); free(p->path); if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { for (i = 0; i < dev->num_configurations; i++) @@ -256,32 +241,12 @@ static inline void windows_device_priv_release(struct libusb_device *dev) } } -struct interface_handle_t { - HANDLE dev_handle; // WinUSB needs an extra handle for the file - HANDLE api_handle; // used by the API to communicate with the device -}; - -struct windows_device_handle_priv { - int active_interface; - struct interface_handle_t interface_handle[USB_MAXINTERFACES]; - int autoclaim_count[USB_MAXINTERFACES]; // For auto-release -}; - -static inline struct windows_device_handle_priv *_device_handle_priv( +static inline struct winusb_device_handle_priv *_device_handle_priv( struct libusb_device_handle *handle) { - return (struct windows_device_handle_priv *)handle->os_priv; + return (struct winusb_device_handle_priv *)handle->os_priv; } -// used for async polling functions -struct windows_transfer_priv { - struct winfd pollable_fd; - uint8_t interface_number; - uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID - uint8_t *hid_dest; // transfer buffer destination, required for HID - size_t hid_expected_size; -}; - // used to match a device driver (including filter drivers) against a supported API struct driver_lookup { char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names @@ -289,34 +254,6 @@ struct driver_lookup { const char* designation; // internal designation (for debug output) }; -/* OLE32 dependency */ -DLL_DECLARE_HANDLE(OLE32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); - -/* Kernel32 dependencies */ -DLL_DECLARE_HANDLE(Kernel32); -/* This call is only available from XP SP2 */ -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); - -/* SetupAPI dependencies */ -DLL_DECLARE_HANDLE(SetupAPI); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, - const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, - PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, - PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); - -/* AdvAPI32 dependencies */ -DLL_DECLARE_HANDLE(AdvAPI32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); - /* * Windows DDK API definitions. Most of it copied from MinGW's includes */ @@ -325,58 +262,64 @@ typedef DEVNODE *PDEVNODE, *PDEVINST; typedef DWORD RETURN_TYPE; typedef RETURN_TYPE CONFIGRET; -#define CR_SUCCESS 0x00000000 -#define CR_NO_SUCH_DEVNODE 0x0000000D +#define CR_SUCCESS 0x00000000 -#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE -#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG -#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING -#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE -#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT +/* Cfgmgr32 dependencies */ +DLL_DECLARE_HANDLE(Cfgmgr32); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); +DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS -#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE -#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE -#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION -#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE -#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE -#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME +/* AdvAPI32 dependencies */ +DLL_DECLARE_HANDLE(AdvAPI32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); -#define USB_GET_NODE_INFORMATION 258 -#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 -#define USB_GET_NODE_CONNECTION_NAME 261 -#define USB_GET_HUB_CAPABILITIES 271 -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 +/* OLE32 dependency */ +DLL_DECLARE_HANDLE(OLE32); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID)); + +/* SetupAPI dependencies */ +DLL_DECLARE_HANDLE(SetupAPI); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, + LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA, + PCSTR, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, + PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, + PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); + + +#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION +#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 #endif -#if !defined(USB_GET_HUB_CAPABILITIES_EX) -#define USB_GET_HUB_CAPABILITIES_EX 276 +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX +#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 #endif -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) +#ifndef USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 #define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 #endif -#ifndef METHOD_BUFFERED -#define METHOD_BUFFERED 0 -#endif -#ifndef FILE_ANY_ACCESS -#define FILE_ANY_ACCESS 0x00000000 -#endif -#ifndef FILE_DEVICE_UNKNOWN -#define FILE_DEVICE_UNKNOWN 0x00000022 -#endif #ifndef FILE_DEVICE_USB -#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN +#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN #endif -#ifndef CTL_CODE -#define CTL_CODE(DeviceType, Function, Method, Access) \ - (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) -#endif +#define USB_CTL_CODE(id) \ + CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ + USB_CTL_CODE(USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX) + +#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ + USB_CTL_CODE(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) typedef enum USB_CONNECTION_STATUS { NoDeviceConnected, @@ -395,42 +338,25 @@ typedef enum USB_HUB_NODE { UsbMIParent } USB_HUB_NODE; -/* Cfgmgr32.dll interface */ -DLL_DECLARE_HANDLE(Cfgmgr32); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); - -#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \ - CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_HUB_CAPABILITIES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_ROOT_HUB_NAME \ - CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_INFORMATION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_NAME \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - // Most of the structures below need to be packed -#pragma pack(push, 1) +#include + +typedef struct _USB_DESCRIPTOR_REQUEST { + ULONG ConnectionIndex; + struct { + UCHAR bmRequest; + UCHAR bRequest; + USHORT wValue; + USHORT wIndex; + USHORT wLength; + } SetupPacket; +// UCHAR Data[0]; +} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT { + USB_DESCRIPTOR_REQUEST req; + USB_CONFIGURATION_DESCRIPTOR desc; +} USB_CONFIGURATION_DESCRIPTOR_SHORT; typedef struct USB_INTERFACE_DESCRIPTOR { UCHAR bLength; @@ -444,103 +370,7 @@ typedef struct USB_INTERFACE_DESCRIPTOR { UCHAR iInterface; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; -typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { - struct { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; - } req; - USB_CONFIGURATION_DESCRIPTOR data; -} USB_CONFIGURATION_DESCRIPTOR_SHORT; - -typedef struct USB_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bEndpointAddress; - UCHAR bmAttributes; - USHORT wMaxPacketSize; - UCHAR bInterval; -} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; - -typedef struct USB_DESCRIPTOR_REQUEST { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; -// UCHAR Data[0]; -} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; - -typedef struct USB_HUB_DESCRIPTOR { - UCHAR bDescriptorLength; - UCHAR bDescriptorType; - UCHAR bNumberOfPorts; - USHORT wHubCharacteristics; - UCHAR bPowerOnToPowerGood; - UCHAR bHubControlCurrent; - UCHAR bRemoveAndPowerMask[64]; -} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; - -typedef struct USB_ROOT_HUB_NAME { - ULONG ActualLength; - WCHAR RootHubName[1]; -} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME; - -typedef struct USB_ROOT_HUB_NAME_FIXED { - ULONG ActualLength; - WCHAR RootHubName[MAX_PATH_LENGTH]; -} USB_ROOT_HUB_NAME_FIXED; - -typedef struct USB_NODE_CONNECTION_NAME { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[1]; -} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME; - -typedef struct USB_NODE_CONNECTION_NAME_FIXED { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[MAX_PATH_LENGTH]; -} USB_NODE_CONNECTION_NAME_FIXED; - -typedef struct USB_HUB_NAME_FIXED { - union { - USB_ROOT_HUB_NAME_FIXED root; - USB_NODE_CONNECTION_NAME_FIXED node; - } u; -} USB_HUB_NAME_FIXED; - -typedef struct USB_HUB_INFORMATION { - USB_HUB_DESCRIPTOR HubDescriptor; - BOOLEAN HubIsBusPowered; -} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION; - -typedef struct USB_MI_PARENT_INFORMATION { - ULONG NumberOfInterfaces; -} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION; - -typedef struct USB_NODE_INFORMATION { - USB_HUB_NODE NodeType; - union { - USB_HUB_INFORMATION HubInformation; - USB_MI_PARENT_INFORMATION MiParentInformation; - } u; -} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION; - -typedef struct USB_PIPE_INFO { - USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG ScheduleOffset; -} USB_PIPE_INFO, *PUSB_PIPE_INFO; - -typedef struct USB_NODE_CONNECTION_INFORMATION_EX { +typedef struct _USB_NODE_CONNECTION_INFORMATION_EX { ULONG ConnectionIndex; USB_DEVICE_DESCRIPTOR DeviceDescriptor; UCHAR CurrentConfigurationValue; @@ -578,25 +408,7 @@ typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 { USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; } USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; -typedef struct USB_HUB_CAP_FLAGS { - ULONG HubIsHighSpeedCapable:1; - ULONG HubIsHighSpeed:1; - ULONG HubIsMultiTtCapable:1; - ULONG HubIsMultiTt:1; - ULONG HubIsRoot:1; - ULONG HubIsArmedWakeOnConnect:1; - ULONG ReservedMBZ:26; -} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS; - -typedef struct USB_HUB_CAPABILITIES { - ULONG HubIs2xCapable:1; -} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES; - -typedef struct USB_HUB_CAPABILITIES_EX { - USB_HUB_CAP_FLAGS CapabilityFlags; -} USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX; - -#pragma pack(pop) +#include /* winusb.dll interface */ @@ -608,36 +420,25 @@ typedef struct USB_HUB_CAPABILITIES_EX { #define AUTO_FLUSH 0x06 #define RAW_IO 0x07 #define MAXIMUM_TRANSFER_SIZE 0x08 -#define AUTO_SUSPEND 0x81 -#define SUSPEND_DELAY 0x83 -#define DEVICE_SPEED 0x01 -#define LowSpeed 0x01 -#define FullSpeed 0x02 -#define HighSpeed 0x03 -typedef enum USBD_PIPE_TYPE { +typedef enum _USBD_PIPE_TYPE { UsbdPipeTypeControl, UsbdPipeTypeIsochronous, UsbdPipeTypeBulk, UsbdPipeTypeInterrupt } USBD_PIPE_TYPE; -typedef struct { - USBD_PIPE_TYPE PipeType; - UCHAR PipeId; - USHORT MaximumPacketSize; - UCHAR Interval; -} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION; +#include -#pragma pack(1) -typedef struct { - UCHAR request_type; - UCHAR request; - USHORT value; - USHORT index; - USHORT length; +typedef struct _WINUSB_SETUP_PACKET { + UCHAR RequestType; + UCHAR Request; + USHORT Value; + USHORT Index; + USHORT Length; } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; -#pragma pack() + +#include typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; @@ -665,59 +466,10 @@ typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)( UCHAR AssociatedInterfaceIndex, PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle ); -typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - PUCHAR AlternateSetting -); -typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR DescriptorType, - UCHAR Index, - USHORT LanguageID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred -); -typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpNumberOfBytesTransferred, - BOOL bWait -); -typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); typedef BOOL (WINAPI *WinUsb_Initialize_t)( HANDLE DeviceHandle, PWINUSB_INTERFACE_HANDLE InterfaceHandle ); -typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG InformationType, - PULONG BufferLength, - PVOID Buffer -); -typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateSettingNumber, - PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor -); -typedef BOOL (WINAPI *WinUsb_QueryPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateInterfaceNumber, - UCHAR PipeIndex, - PWINUSB_PIPE_INFORMATION PipeInformation -); typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID, @@ -726,6 +478,9 @@ typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( PULONG LengthTransferred, LPOVERLAPPED Overlapped ); +typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle +); typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID @@ -741,12 +496,6 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( ULONG ValueLength, PVOID Value ); -typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - ULONG ValueLength, - PVOID Value -); typedef BOOL (WINAPI *WinUsb_WritePipe_t)( WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR PipeID, @@ -755,9 +504,6 @@ typedef BOOL (WINAPI *WinUsb_WritePipe_t)( PULONG LengthTransferred, LPOVERLAPPED Overlapped ); -typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle -); /* /!\ These must match the ones from the official libusbk.h */ typedef enum _KUSB_FNID { @@ -803,8 +549,7 @@ typedef struct _KLIB_VERSION { INT Minor; INT Micro; INT Nano; -} KLIB_VERSION; -typedef KLIB_VERSION* PKLIB_VERSION; +} KLIB_VERSION, *PKLIB_VERSION; typedef BOOL (WINAPI *LibK_GetProcAddress_t)( PVOID *ProcAddress, @@ -816,29 +561,63 @@ typedef VOID (WINAPI *LibK_GetVersion_t)( PKLIB_VERSION Version ); +//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths +typedef struct _KISO_PACKET { + UINT offset; + USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity + USHORT status; +} KISO_PACKET, *PKISO_PACKET; + +typedef enum _KISO_FLAG { + KISO_FLAG_NONE = 0, + KISO_FLAG_SET_START_FRAME = 0x00000001, +} KISO_FLAG; + +//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version +typedef struct _KISO_CONTEXT { + KISO_FLAG Flags; + UINT StartFrame; + SHORT ErrorCount; + SHORT NumberOfPackets; + UINT UrbHdrStatus; + KISO_PACKET IsoPackets[0]; +} KISO_CONTEXT, *PKISO_CONTEXT; + +typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + +typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)( + WINUSB_INTERFACE_HANDLE InterfaceHandle, + UCHAR PipeID, + PUCHAR Buffer, + ULONG BufferLength, + LPOVERLAPPED Overlapped, + PKISO_CONTEXT IsoContext +); + struct winusb_interface { bool initialized; + bool CancelIoEx_supported; WinUsb_AbortPipe_t AbortPipe; WinUsb_ControlTransfer_t ControlTransfer; WinUsb_FlushPipe_t FlushPipe; WinUsb_Free_t Free; WinUsb_GetAssociatedInterface_t GetAssociatedInterface; - WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting; - WinUsb_GetDescriptor_t GetDescriptor; - WinUsb_GetOverlappedResult_t GetOverlappedResult; - WinUsb_GetPipePolicy_t GetPipePolicy; - WinUsb_GetPowerPolicy_t GetPowerPolicy; WinUsb_Initialize_t Initialize; - WinUsb_QueryDeviceInformation_t QueryDeviceInformation; - WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings; - WinUsb_QueryPipe_t QueryPipe; WinUsb_ReadPipe_t ReadPipe; + WinUsb_ResetDevice_t ResetDevice; WinUsb_ResetPipe_t ResetPipe; WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; WinUsb_SetPipePolicy_t SetPipePolicy; - WinUsb_SetPowerPolicy_t SetPowerPolicy; WinUsb_WritePipe_t WritePipe; - WinUsb_ResetDevice_t ResetDevice; + WinUsb_IsoReadPipe_t IsoReadPipe; + WinUsb_IsoWritePipe_t IsoWritePipe; }; /* hid.dll interface */ @@ -846,34 +625,10 @@ struct winusb_interface { #define HIDP_STATUS_SUCCESS 0x110000 typedef void * PHIDP_PREPARSED_DATA; -#pragma pack(1) -typedef struct { - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; -} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; -#pragma pack() +#include +#include typedef USHORT USAGE; -typedef struct { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT NumberLinkCollectionNodes; - USHORT NumberInputButtonCaps; - USHORT NumberInputValueCaps; - USHORT NumberInputDataIndices; - USHORT NumberOutputButtonCaps; - USHORT NumberOutputValueCaps; - USHORT NumberOutputDataIndices; - USHORT NumberFeatureButtonCaps; - USHORT NumberFeatureValueCaps; - USHORT NumberFeatureDataIndices; -} HIDP_CAPS, *PHIDP_CAPS; typedef enum _HIDP_REPORT_TYPE { HidP_Input, @@ -919,19 +674,7 @@ typedef struct _HIDP_VALUE_CAPS { } HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; DLL_DECLARE_HANDLE(hid); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG)); DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); \ No newline at end of file +DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/strerror.c b/vendor/github.com/karalabe/usb/libusb/libusb/strerror.c similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/strerror.c rename to vendor/github.com/karalabe/usb/libusb/libusb/strerror.c diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/sync.c b/vendor/github.com/karalabe/usb/libusb/libusb/sync.c similarity index 100% rename from vendor/github.com/karalabe/hid/libusb/libusb/sync.c rename to vendor/github.com/karalabe/usb/libusb/libusb/sync.c diff --git a/vendor/github.com/karalabe/hid/libusb/libusb/version.h b/vendor/github.com/karalabe/usb/libusb/libusb/version.h similarity index 94% rename from vendor/github.com/karalabe/hid/libusb/libusb/version.h rename to vendor/github.com/karalabe/usb/libusb/libusb/version.h index 6ce48a7d0..c6dfe3709 100644 --- a/vendor/github.com/karalabe/hid/libusb/libusb/version.h +++ b/vendor/github.com/karalabe/usb/libusb/libusb/version.h @@ -7,7 +7,7 @@ #define LIBUSB_MINOR 0 #endif #ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 21 +#define LIBUSB_MICRO 22 #endif #ifndef LIBUSB_NANO #define LIBUSB_NANO 0 diff --git a/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h b/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h new file mode 100644 index 000000000..90a782a6b --- /dev/null +++ b/vendor/github.com/karalabe/usb/libusb/libusb/version_nano.h @@ -0,0 +1 @@ +#define LIBUSB_NANO 11312 diff --git a/vendor/github.com/karalabe/usb/raw_disabled.go b/vendor/github.com/karalabe/usb/raw_disabled.go new file mode 100644 index 000000000..a05ef8ebb --- /dev/null +++ b/vendor/github.com/karalabe/usb/raw_disabled.go @@ -0,0 +1,42 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2017 The library Authors +// +// This 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 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 library. If not, see . + +// +build !freebsd,!linux,!darwin,!windows ios !cgo + +package usb + +// RawDevice is a live raw USB connected device handle. On platforms that this file +// implements, the type lacks the actual USB device and all methods are noop. +type RawDevice struct { + DeviceInfo // Embed the infos for easier access +} + +// Close releases the USB device handle. On platforms that this file implements, +// the method is just a noop. +func (dev *RawDevice) Close() error { + return ErrUnsupportedPlatform +} + +// Write sends a binary blob to a USB device. On platforms that this file +// implements, the method just returns an error. +func (dev *RawDevice) Write(b []byte) (int, error) { + return 0, ErrUnsupportedPlatform +} + +// Read retrieves a binary blob from a USB device. On platforms that this file +// implements, the method just returns an error. +func (dev *RawDevice) Read(b []byte) (int, error) { + return 0, ErrUnsupportedPlatform +} diff --git a/vendor/github.com/karalabe/usb/raw_enabled.go b/vendor/github.com/karalabe/usb/raw_enabled.go new file mode 100644 index 000000000..326ac97ad --- /dev/null +++ b/vendor/github.com/karalabe/usb/raw_enabled.go @@ -0,0 +1,253 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo + +package usb + +/* + #include "./libusb/libusb/libusb.h" + + // ctx is a global libusb context to interact with devices through. + libusb_context* ctx; +*/ +import "C" + +import ( + "fmt" + "reflect" + "sync" + "unsafe" +) + +// enumerateRaw returns a list of all the USB devices attached to the system which +// match the vendor and product id: +// - If the vendor id is set to 0 then any vendor matches. +// - If the product id is set to 0 then any product matches. +// - If the vendor and product id are both 0, all USB devices are returned. +func enumerateRaw(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + // Enumerate the devices, and free all the matching refcounts (we'll reopen any + // explicitly requested). + infos, err := enumerateRawWithRef(vendorID, productID) + for _, info := range infos { + C.libusb_unref_device(info.rawDevice.(*C.libusb_device)) + } + // If enumeration failed, don't return anything, otherwise everything + if err != nil { + return nil, err + } + return infos, nil +} + +// enumerateRawWithRef is the internal device enumerator that retains 1 reference +// to every matched device so they may selectively be opened on request. +func enumerateRawWithRef(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + // Ensure we have a libusb context to interact through. The enumerate call is + // protexted by a mutex outside, so it's fine to do the below check and init. + if C.ctx == nil { + if err := fromRawErrno(C.libusb_init((**C.libusb_context)(&C.ctx))); err != nil { + return nil, fmt.Errorf("failed to initialize libusb: %v", err) + } + } + // Retrieve all the available USB devices and wrap them in Go + var deviceList **C.libusb_device + count := C.libusb_get_device_list(C.ctx, &deviceList) + if count < 0 { + return nil, rawError(count) + } + defer C.libusb_free_device_list(deviceList, 1) + + var devices []*C.libusb_device + *(*reflect.SliceHeader)(unsafe.Pointer(&devices)) = reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(deviceList)), + Len: int(count), + Cap: int(count), + } + // + var infos []DeviceInfo + for devnum, dev := range devices { + // Retrieve the libusb device descriptor and skip non-queried ones + var desc C.struct_libusb_device_descriptor + if err := fromRawErrno(C.libusb_get_device_descriptor(dev, &desc)); err != nil { + return infos, fmt.Errorf("failed to get device %d descriptor: %v", devnum, err) + } + if (vendorID > 0 && uint16(desc.idVendor) != vendorID) || (productID > 0 && uint16(desc.idProduct) != productID) { + continue + } + // Skip HID devices, they are handled directly by OS libraries + if desc.bDeviceClass == C.LIBUSB_CLASS_HID { + continue + } + // Iterate over all the configurations and find raw interfaces + for cfgnum := 0; cfgnum < int(desc.bNumConfigurations); cfgnum++ { + // Retrieve the all the possible USB configurations of the device + var cfg *C.struct_libusb_config_descriptor + if err := fromRawErrno(C.libusb_get_config_descriptor(dev, C.uint8_t(cfgnum), &cfg)); err != nil { + return infos, fmt.Errorf("failed to get device %d config %d: %v", devnum, cfgnum, err) + } + var ifaces []C.struct_libusb_interface + *(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(cfg._interface)), + Len: int(cfg.bNumInterfaces), + Cap: int(cfg.bNumInterfaces), + } + // Drill down into each advertised interface + for ifacenum, iface := range ifaces { + if iface.num_altsetting == 0 { + continue + } + var alts []C.struct_libusb_interface_descriptor + *(*reflect.SliceHeader)(unsafe.Pointer(&alts)) = reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(iface.altsetting)), + Len: int(iface.num_altsetting), + Cap: int(iface.num_altsetting), + } + for _, alt := range alts { + // Skip HID interfaces, they are handled directly by OS libraries + if alt.bInterfaceClass == C.LIBUSB_CLASS_HID { + continue + } + // Find the endpoints that can speak libusb interrupts + var ends []C.struct_libusb_endpoint_descriptor + *(*reflect.SliceHeader)(unsafe.Pointer(&ends)) = reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(alt.endpoint)), + Len: int(alt.bNumEndpoints), + Cap: int(alt.bNumEndpoints), + } + var reader, writer *uint8 + for _, end := range ends { + // Skip any non-interrupt endpoints + if end.bmAttributes != C.LIBUSB_TRANSFER_TYPE_INTERRUPT { + continue + } + if end.bEndpointAddress&C.LIBUSB_ENDPOINT_IN == C.LIBUSB_ENDPOINT_IN { + reader = new(uint8) + *reader = uint8(end.bEndpointAddress) + } else { + writer = new(uint8) + *writer = uint8(end.bEndpointAddress) + } + } + // If both in and out interrupts are available, match the device + if reader != nil && writer != nil { + // Enumeration matched, bump the device refcount to avoid cleaning it up + C.libusb_ref_device(dev) + + port := uint8(C.libusb_get_port_number(dev)) + infos = append(infos, DeviceInfo{ + Path: fmt.Sprintf("%04x:%04x:%02d", vendorID, uint16(desc.idProduct), port), + VendorID: uint16(desc.idVendor), + ProductID: uint16(desc.idProduct), + Interface: ifacenum, + rawDevice: dev, + rawPort: &port, + rawReader: reader, + rawWriter: writer, + }) + } + } + } + } + } + return infos, nil +} + +// openRaw connects to a low level libusb device by its path name. +func openRaw(info DeviceInfo) (*rawDevice, error) { + // Enumerate all the devices matching this particular info + matches, err := enumerateRawWithRef(info.VendorID, info.ProductID) + if err != nil { + // Enumeration failed, make sure any subresults are released + for _, match := range matches { + C.libusb_unref_device(match.rawDevice.(*C.libusb_device)) + } + return nil, err + } + // Find the specific endpoint we're interested in + var device *C.libusb_device + for _, match := range matches { + // Keep the matching device reference, release anything else + if device == nil && *match.rawPort == *info.rawPort && match.Interface == info.Interface { + device = match.rawDevice.(*C.libusb_device) + } else { + C.libusb_unref_device(match.rawDevice.(*C.libusb_device)) + } + } + if device == nil { + return nil, fmt.Errorf("failed to open device: not found") + } + // Open the mathcing device + info.rawDevice = device + + var handle *C.struct_libusb_device_handle + if err := fromRawErrno(C.libusb_open(info.rawDevice.(*C.libusb_device), (**C.struct_libusb_device_handle)(&handle))); err != nil { + return nil, fmt.Errorf("failed to open device: %v", err) + } + if err := fromRawErrno(C.libusb_claim_interface(handle, (C.int)(info.Interface))); err != nil { + C.libusb_close(handle) + return nil, fmt.Errorf("failed to claim interface: %v", err) + } + return &rawDevice{ + DeviceInfo: info, + handle: handle, + }, nil +} + +// rawDevice is a live low level USB connected device handle. +type rawDevice struct { + DeviceInfo // Embed the infos for easier access + + handle *C.struct_libusb_device_handle // Low level USB device to communicate through + lock sync.Mutex +} + +// Close releases the raw USB device handle. +func (dev *rawDevice) Close() error { + dev.lock.Lock() + defer dev.lock.Unlock() + + if dev.handle != nil { + C.libusb_release_interface(dev.handle, (C.int)(dev.Interface)) + C.libusb_close(dev.handle) + dev.handle = nil + } + C.libusb_unref_device(dev.rawDevice.(*C.libusb_device)) + + return nil +} + +// Write sends a binary blob to a low level USB device. +func (dev *rawDevice) Write(b []byte) (int, error) { + dev.lock.Lock() + defer dev.lock.Unlock() + + var transferred C.int + if err := fromRawErrno(C.libusb_interrupt_transfer(dev.handle, (C.uchar)(*dev.rawWriter), (*C.uchar)(&b[0]), (C.int)(len(b)), &transferred, (C.uint)(0))); err != nil { + return 0, fmt.Errorf("failed to write to device: %v", err) + } + return int(transferred), nil +} + +// Read retrieves a binary blob from a low level USB device. +func (dev *rawDevice) Read(b []byte) (int, error) { + dev.lock.Lock() + defer dev.lock.Unlock() + + var transferred C.int + if err := fromRawErrno(C.libusb_interrupt_transfer(dev.handle, (C.uchar)(*dev.rawReader), (*C.uchar)(&b[0]), (C.int)(len(b)), &transferred, (C.uint)(0))); err != nil { + return 0, fmt.Errorf("failed to read from device: %v", err) + } + return int(transferred), nil +} diff --git a/vendor/github.com/karalabe/usb/raw_errors.go b/vendor/github.com/karalabe/usb/raw_errors.go new file mode 100644 index 000000000..9e071f861 --- /dev/null +++ b/vendor/github.com/karalabe/usb/raw_errors.go @@ -0,0 +1,74 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Copyright 2016 the gousb Authors. All rights reserved. +// +// 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. + +package usb + +import ( + "fmt" +) + +// #include "./libusb/libusb/libusb.h" +import "C" + +// rawError is an error code from libusb. +type rawError C.int + +// Error implements the error interface. +func (e rawError) Error() string { + return fmt.Sprintf("libusb: %s [code %d]", rawErrorString[e], e) +} + +// fromRawErrno converts a raw libusb error into a Go type. +func fromRawErrno(errno C.int) error { + err := rawError(errno) + if err == errSuccess { + return nil + } + return err +} + +const ( + errSuccess rawError = C.LIBUSB_SUCCESS + errIO rawError = C.LIBUSB_ERROR_IO + errInvalidParam rawError = C.LIBUSB_ERROR_INVALID_PARAM + errAccess rawError = C.LIBUSB_ERROR_ACCESS + errNoDevice rawError = C.LIBUSB_ERROR_NO_DEVICE + errNotFound rawError = C.LIBUSB_ERROR_NOT_FOUND + errBusy rawError = C.LIBUSB_ERROR_BUSY + errTimeout rawError = C.LIBUSB_ERROR_TIMEOUT + errOverflow rawError = C.LIBUSB_ERROR_OVERFLOW + errPipe rawError = C.LIBUSB_ERROR_PIPE + errInterrupted rawError = C.LIBUSB_ERROR_INTERRUPTED + errNoMem rawError = C.LIBUSB_ERROR_NO_MEM + errNotSupported rawError = C.LIBUSB_ERROR_NOT_SUPPORTED + errOther rawError = C.LIBUSB_ERROR_OTHER +) + +var rawErrorString = map[rawError]string{ + errSuccess: "success", + errIO: "i/o error", + errInvalidParam: "invalid param", + errAccess: "bad access", + errNoDevice: "no device", + errNotFound: "not found", + errBusy: "device or resource busy", + errTimeout: "timeout", + errOverflow: "overflow", + errPipe: "pipe error", + errInterrupted: "interrupted", + errNoMem: "out of memory", + errNotSupported: "not supported", + errOther: "unknown error", +} diff --git a/vendor/github.com/karalabe/usb/usb.go b/vendor/github.com/karalabe/usb/usb.go new file mode 100644 index 000000000..96a1e2502 --- /dev/null +++ b/vendor/github.com/karalabe/usb/usb.go @@ -0,0 +1,68 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// Package usb provide interfaces for generic USB devices. +package usb + +import "errors" + +// ErrDeviceClosed is returned for operations where the device closed before or +// during the execution. +var ErrDeviceClosed = errors.New("usb: device closed") + +// ErrUnsupportedPlatform is returned for all operations where the underlying +// operating system is not supported by the library. +var ErrUnsupportedPlatform = errors.New("usb: unsupported platform") + +// DeviceInfo contains all the information we know about a USB device. In case of +// HID devices, that might be a lot more extensive (empty fields for raw USB). +type DeviceInfo struct { + Path string // Platform-specific device path + VendorID uint16 // Device Vendor ID + ProductID uint16 // Device Product ID + Release uint16 // Device Release Number in binary-coded decimal, also known as Device Version Number + Serial string // Serial Number + Manufacturer string // Manufacturer String + Product string // Product string + UsagePage uint16 // Usage Page for this Device/Interface (Windows/Mac only) + Usage uint16 // Usage for this Device/Interface (Windows/Mac only) + + // The USB interface which this logical device + // represents. Valid on both Linux implementations + // in all cases, and valid on the Windows implementation + // only if the device contains more than one interface. + Interface int + + // Raw low level libusb endpoint data for simplified communication + rawDevice interface{} + rawPort *uint8 // Pointer to differentiate between unset and port 0 + rawReader *uint8 // Pointer to differentiate between unset and endpoint 0 + rawWriter *uint8 // Pointer to differentiate between unset and endpoint 0 +} + +// Device is a generic USB device interface. It may either be backed by a USB HID +// device or a low level raw (libusb) device. +type Device interface { + // Close releases the USB device handle. + Close() error + + // Write sends a binary blob to a USB device. For HID devices write uses reports, + // for low level USB write uses interrupt transfers. + Write(b []byte) (int, error) + + // Read retrieves a binary blob from a USB device. For HID devices read uses + // reports, for low level USB read uses interrupt transfers. + Read(b []byte) (int, error) +} diff --git a/vendor/github.com/karalabe/usb/usb_disabled.go b/vendor/github.com/karalabe/usb/usb_disabled.go new file mode 100644 index 000000000..77c900761 --- /dev/null +++ b/vendor/github.com/karalabe/usb/usb_disabled.go @@ -0,0 +1,51 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// +build !freebsd,!linux,!darwin,!windows ios !cgo + +package usb + +// Supported returns whether this platform is supported by the USB library or not. +// The goal of this method is to allow programatically handling platforms that do +// not support USB and not having to fall back to build constraints. +func Supported() bool { + return false +} + +// Enumerate returns a list of all the USB devices attached to the system which +// match the vendor and product id. On platforms that this file implements the +// function is a noop and returns an empty list always. +func Enumerate(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + return nil, nil +} + +// EnumerateRaw returns a list of all the USB devices attached to the system which +// match the vendor and product id. On platforms that this file implements the +// function is a noop and returns an empty list always. +func EnumerateRaw(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + return nil, nil +} + +// EnumerateHid returns a list of all the HID devices attached to the system which +// match the vendor and product id. On platforms that this file implements the +// function is a noop and returns an empty list always. +func EnumerateHid(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + return nil, nil +} + +// Open connects to a previsouly discovered USB device. +func (info DeviceInfo) Open() (Device, error) { + return nil, ErrUnsupportedPlatform +} diff --git a/vendor/github.com/karalabe/usb/usb_enabled.go b/vendor/github.com/karalabe/usb/usb_enabled.go new file mode 100644 index 000000000..6ba37af7b --- /dev/null +++ b/vendor/github.com/karalabe/usb/usb_enabled.go @@ -0,0 +1,98 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2019 The library Authors +// +// This 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 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 library. If not, see . + +// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo + +package usb + +import ( + "sync" +) + +// enumerateLock is a mutex serializing access to USB device enumeration needed +// by the macOS USB HID system calls, which require 2 consecutive method calls +// for enumeration, causing crashes if called concurrently. +// +// For more details, see: +// https://developer.apple.com/documentation/iokit/1438371-iohidmanagersetdevicematching +// > "subsequent calls will cause the hid manager to release previously enumerated devices" +var enumerateLock sync.Mutex + +// Supported returns whether this platform is supported by the USB library or not. +// The goal of this method is to allow programatically handling platforms that do +// not support USB and not having to fall back to build constraints. +func Supported() bool { + return true +} + +// Enumerate returns a list of all the USB devices attached to the system which +// match the vendor and product id: +// - If the vendor id is set to 0 then any vendor matches. +// - If the product id is set to 0 then any product matches. +// - If the vendor and product id are both 0, all devices are returned. +// +// For any device that is HID capable, the enumeration will return an interface +// to the HID endpoints. For pure raw USB access, please use EnumerateRaw. +func Enumerate(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + enumerateLock.Lock() + defer enumerateLock.Unlock() + + // Enumerate all the raw USB devices and skip the HID ones + raws, err := enumerateRaw(vendorID, productID) + if err != nil { + return nil, err + } + // Enumerate all the HID USB devices + hids, err := enumerateHid(vendorID, productID) + if err != nil { + return nil, err + } + return append(raws, hids...), nil +} + +// EnumerateRaw returns a list of all the USB devices attached to the system which +// match the vendor and product id: +// - If the vendor id is set to 0 then any vendor matches. +// - If the product id is set to 0 then any product matches. +// - If the vendor and product id are both 0, all devices are returned. +func EnumerateRaw(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + enumerateLock.Lock() + defer enumerateLock.Unlock() + + return enumerateRaw(vendorID, productID) +} + +// EnumerateHid returns a list of all the HID devices attached to the system which +// match the vendor and product id: +// - If the vendor id is set to 0 then any vendor matches. +// - If the product id is set to 0 then any product matches. +// - If the vendor and product id are both 0, all devices are returned. +func EnumerateHid(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + enumerateLock.Lock() + defer enumerateLock.Unlock() + + return enumerateHid(vendorID, productID) +} + +// Open connects to a previsouly discovered USB device. +func (info DeviceInfo) Open() (Device, error) { + enumerateLock.Lock() + defer enumerateLock.Unlock() + + if info.rawDevice == nil { + return openHid(info) + } + return openRaw(info) +} diff --git a/vendor/github.com/karalabe/hid/wchar.go b/vendor/github.com/karalabe/usb/wchar.go similarity index 98% rename from vendor/github.com/karalabe/hid/wchar.go rename to vendor/github.com/karalabe/usb/wchar.go index d103beff5..cbc7e4d56 100644 --- a/vendor/github.com/karalabe/hid/wchar.go +++ b/vendor/github.com/karalabe/usb/wchar.go @@ -7,9 +7,9 @@ // https://github.com/orofarne/gowchar/blob/master/LICENSE // +build !ios -// +build linux darwin windows +// +build freebsd linux darwin windows -package hid +package usb /* #include diff --git a/vendor/github.com/lib/pq/.travis.sh b/vendor/github.com/lib/pq/.travis.sh index a297dc452..ebf447030 100644 --- a/vendor/github.com/lib/pq/.travis.sh +++ b/vendor/github.com/lib/pq/.travis.sh @@ -70,17 +70,4 @@ postgresql_uninstall() { sudo rm -rf /var/lib/postgresql } -megacheck_install() { - # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous - # new error messages in old code. - go get -d honnef.co/go/tools/... - git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION - go install honnef.co/go/tools/cmd/megacheck - megacheck --version -} - -golint_install() { - go get github.com/golang/lint/golint -} - $1 diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml index 18556e089..8396f5d9d 100644 --- a/vendor/github.com/lib/pq/.travis.yml +++ b/vendor/github.com/lib/pq/.travis.yml @@ -1,9 +1,8 @@ language: go go: - - 1.8.x - - 1.9.x - - 1.10.x + - 1.11.x + - 1.12.x - master sudo: true @@ -14,16 +13,11 @@ env: - PQGOSSLTESTS=1 - PQSSLCERTTEST_PATH=$PWD/certs - PGHOST=127.0.0.1 - - MEGACHECK_VERSION=2017.2.2 matrix: - PGVERSION=10 - PGVERSION=9.6 - PGVERSION=9.5 - PGVERSION=9.4 - - PGVERSION=9.3 - - PGVERSION=9.2 - - PGVERSION=9.1 - - PGVERSION=9.0 before_install: - ./.travis.sh postgresql_uninstall @@ -31,9 +25,9 @@ before_install: - ./.travis.sh postgresql_install - ./.travis.sh postgresql_configure - ./.travis.sh client_configure - - ./.travis.sh megacheck_install - - ./.travis.sh golint_install - go get golang.org/x/tools/cmd/goimports + - go get golang.org/x/lint/golint + - GO111MODULE=on go get honnef.co/go/tools/cmd/staticcheck@2019.2.1 before_script: - createdb pqgotest @@ -44,7 +38,7 @@ script: - > goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' - go vet ./... - - megacheck -go 1.8 ./... + - staticcheck -go 1.11 ./... - golint ./... - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md index d71f3c2c3..385fe7350 100644 --- a/vendor/github.com/lib/pq/README.md +++ b/vendor/github.com/lib/pq/README.md @@ -10,7 +10,7 @@ ## Docs For detailed documentation and basic usage examples, please see the package -documentation at . +documentation at . ## Tests diff --git a/vendor/github.com/lib/pq/buf.go b/vendor/github.com/lib/pq/buf.go index 666b0012a..4b0a0a8f7 100644 --- a/vendor/github.com/lib/pq/buf.go +++ b/vendor/github.com/lib/pq/buf.go @@ -66,7 +66,7 @@ func (b *writeBuf) int16(n int) { } func (b *writeBuf) string(s string) { - b.buf = append(b.buf, (s + "\000")...) + b.buf = append(append(b.buf, s...), '\000') } func (b *writeBuf) byte(c byte) { diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index 43c8df29f..55152b124 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -2,7 +2,9 @@ package pq import ( "bufio" + "context" "crypto/md5" + "crypto/sha256" "database/sql" "database/sql/driver" "encoding/binary" @@ -20,6 +22,7 @@ import ( "unicode" "github.com/lib/pq/oid" + "github.com/lib/pq/scram" ) // Common error types @@ -89,13 +92,25 @@ type Dialer interface { DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) } -type defaultDialer struct{} - -func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) { - return net.Dial(ntw, addr) +// DialerContext is the context-aware dialer interface. +type DialerContext interface { + DialContext(ctx context.Context, network, address string) (net.Conn, error) } -func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout(ntw, addr, timeout) + +type defaultDialer struct { + d net.Dialer +} + +func (d defaultDialer) Dial(network, address string) (net.Conn, error) { + return d.d.Dial(network, address) +} +func (d defaultDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + return d.DialContext(ctx, network, address) +} +func (d defaultDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + return d.d.DialContext(ctx, network, address) } type conn struct { @@ -244,90 +259,35 @@ func (cn *conn) writeBuf(b byte) *writeBuf { } } -// Open opens a new connection to the database. name is a connection string. +// Open opens a new connection to the database. dsn is a connection string. // Most users should only use it through database/sql package from the standard // library. -func Open(name string) (_ driver.Conn, err error) { - return DialOpen(defaultDialer{}, name) +func Open(dsn string) (_ driver.Conn, err error) { + return DialOpen(defaultDialer{}, dsn) } // DialOpen opens a new connection to the database using a dialer. -func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { +func DialOpen(d Dialer, dsn string) (_ driver.Conn, err error) { + c, err := NewConnector(dsn) + if err != nil { + return nil, err + } + c.dialer = d + return c.open(context.Background()) +} + +func (c *Connector) open(ctx context.Context) (cn *conn, err error) { // Handle any panics during connection initialization. Note that we // specifically do *not* want to use errRecover(), as that would turn any // connection errors into ErrBadConns, hiding the real error message from // the user. defer errRecoverNoErrBadConn(&err) - o := make(values) + o := c.opts - // A number of defaults are applied here, in this order: - // - // * Very low precedence defaults applied in every situation - // * Environment variables - // * Explicitly passed connection information - o["host"] = "localhost" - o["port"] = "5432" - // N.B.: Extra float digits should be set to 3, but that breaks - // Postgres 8.4 and older, where the max is 2. - o["extra_float_digits"] = "2" - for k, v := range parseEnviron(os.Environ()) { - o[k] = v - } - - if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") { - name, err = ParseURL(name) - if err != nil { - return nil, err - } - } - - if err := parseOpts(name, o); err != nil { - return nil, err - } - - // Use the "fallback" application name if necessary - if fallback, ok := o["fallback_application_name"]; ok { - if _, ok := o["application_name"]; !ok { - o["application_name"] = fallback - } - } - - // We can't work with any client_encoding other than UTF-8 currently. - // However, we have historically allowed the user to set it to UTF-8 - // explicitly, and there's no reason to break such programs, so allow that. - // Note that the "options" setting could also set client_encoding, but - // parsing its value is not worth it. Instead, we always explicitly send - // client_encoding as a separate run-time parameter, which should override - // anything set in options. - if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) { - return nil, errors.New("client_encoding must be absent or 'UTF8'") - } - o["client_encoding"] = "UTF8" - // DateStyle needs a similar treatment. - if datestyle, ok := o["datestyle"]; ok { - if datestyle != "ISO, MDY" { - panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v", - "ISO, MDY", datestyle)) - } - } else { - o["datestyle"] = "ISO, MDY" - } - - // If a user is not provided by any other means, the last - // resort is to use the current operating system provided user - // name. - if _, ok := o["user"]; !ok { - u, err := userCurrent() - if err != nil { - return nil, err - } - o["user"] = u - } - - cn := &conn{ + cn = &conn{ opts: o, - dialer: d, + dialer: c.dialer, } err = cn.handleDriverSettings(o) if err != nil { @@ -335,13 +295,16 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { } cn.handlePgpass(o) - cn.c, err = dial(d, o) + cn.c, err = dial(ctx, c.dialer, o) if err != nil { return nil, err } err = cn.ssl(o) if err != nil { + if cn.c != nil { + cn.c.Close() + } return nil, err } @@ -364,10 +327,10 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { return cn, err } -func dial(d Dialer, o values) (net.Conn, error) { - ntw, addr := network(o) +func dial(ctx context.Context, d Dialer, o values) (net.Conn, error) { + network, address := network(o) // SSL is not necessary or supported over UNIX domain sockets - if ntw == "unix" { + if network == "unix" { o["sslmode"] = "disable" } @@ -378,19 +341,30 @@ func dial(d Dialer, o values) (net.Conn, error) { return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err) } duration := time.Duration(seconds) * time.Second + // connect_timeout should apply to the entire connection establishment // procedure, so we both use a timeout for the TCP connection // establishment and set a deadline for doing the initial handshake. // The deadline is then reset after startup() is done. deadline := time.Now().Add(duration) - conn, err := d.DialTimeout(ntw, addr, duration) + var conn net.Conn + if dctx, ok := d.(DialerContext); ok { + ctx, cancel := context.WithTimeout(ctx, duration) + defer cancel() + conn, err = dctx.DialContext(ctx, network, address) + } else { + conn, err = d.DialTimeout(network, address, duration) + } if err != nil { return nil, err } err = conn.SetDeadline(deadline) return conn, err } - return d.Dial(ntw, addr) + if dctx, ok := d.(DialerContext); ok { + return dctx.DialContext(ctx, network, address) + } + return d.Dial(network, address) } func network(o values) (string, string) { @@ -576,7 +550,7 @@ func (cn *conn) Commit() (err error) { // would get the same behaviour if you issued a COMMIT in a failed // transaction, so it's also the least surprising thing to do here. if cn.txnStatus == txnStatusInFailedTransaction { - if err := cn.Rollback(); err != nil { + if err := cn.rollback(); err != nil { return err } return ErrInFailedTransaction @@ -603,7 +577,10 @@ func (cn *conn) Rollback() (err error) { return driver.ErrBadConn } defer cn.errRecover(&err) + return cn.rollback() +} +func (cn *conn) rollback() (err error) { cn.checkIsInTransaction(true) _, commandTag, err := cn.simpleExec("ROLLBACK") if err != nil { @@ -704,7 +681,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) { // res might be non-nil here if we received a previous // CommandComplete, but that's fine; just overwrite it res = &rows{cn: cn} - res.colNames, res.colFmts, res.colTyps = parsePortalRowDescribe(r) + res.rowsHeader = parsePortalRowDescribe(r) // To work around a bug in QueryRow in Go 1.2 and earlier, wait // until the first DataRow has been received. @@ -861,17 +838,15 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) { cn.readParseResponse() cn.readBindResponse() rows := &rows{cn: cn} - rows.colNames, rows.colFmts, rows.colTyps = cn.readPortalDescribeResponse() + rows.rowsHeader = cn.readPortalDescribeResponse() cn.postExecuteWorkaround() return rows, nil } st := cn.prepareTo(query, "") st.exec(args) return &rows{ - cn: cn, - colNames: st.colNames, - colTyps: st.colTyps, - colFmts: st.colFmts, + cn: cn, + rowsHeader: st.rowsHeader, }, nil } @@ -992,7 +967,6 @@ func (cn *conn) recv() (t byte, r *readBuf) { if err != nil { panic(err) } - switch t { case 'E': panic(parseError(r)) @@ -1163,6 +1137,55 @@ func (cn *conn) auth(r *readBuf, o values) { if r.int32() != 0 { errorf("unexpected authentication response: %q", t) } + case 10: + sc := scram.NewClient(sha256.New, o["user"], o["password"]) + sc.Step(nil) + if sc.Err() != nil { + errorf("SCRAM-SHA-256 error: %s", sc.Err().Error()) + } + scOut := sc.Out() + + w := cn.writeBuf('p') + w.string("SCRAM-SHA-256") + w.int32(len(scOut)) + w.bytes(scOut) + cn.send(w) + + t, r := cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 11 { + errorf("unexpected authentication response: %q", t) + } + + nextStep := r.next(len(*r)) + sc.Step(nextStep) + if sc.Err() != nil { + errorf("SCRAM-SHA-256 error: %s", sc.Err().Error()) + } + + scOut = sc.Out() + w = cn.writeBuf('p') + w.bytes(scOut) + cn.send(w) + + t, r = cn.recv() + if t != 'R' { + errorf("unexpected password response: %q", t) + } + + if r.int32() != 12 { + errorf("unexpected authentication response: %q", t) + } + + nextStep = r.next(len(*r)) + sc.Step(nextStep) + if sc.Err() != nil { + errorf("SCRAM-SHA-256 error: %s", sc.Err().Error()) + } + default: errorf("unknown authentication response: %d", code) } @@ -1180,12 +1203,10 @@ var colFmtDataAllBinary = []byte{0, 1, 0, 1} var colFmtDataAllText = []byte{0, 0} type stmt struct { - cn *conn - name string - colNames []string - colFmts []format + cn *conn + name string + rowsHeader colFmtData []byte - colTyps []fieldDesc paramTyps []oid.Oid closed bool } @@ -1231,10 +1252,8 @@ func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) { st.exec(v) return &rows{ - cn: st.cn, - colNames: st.colNames, - colTyps: st.colTyps, - colFmts: st.colFmts, + cn: st.cn, + rowsHeader: st.rowsHeader, }, nil } @@ -1344,16 +1363,22 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) { return driver.RowsAffected(n), commandTag } -type rows struct { - cn *conn - finish func() +type rowsHeader struct { colNames []string colTyps []fieldDesc colFmts []format - done bool - rb readBuf - result driver.Result - tag string +} + +type rows struct { + cn *conn + finish func() + rowsHeader + done bool + rb readBuf + result driver.Result + tag string + + next *rowsHeader } func (rs *rows) Close() error { @@ -1440,7 +1465,8 @@ func (rs *rows) Next(dest []driver.Value) (err error) { } return case 'T': - rs.colNames, rs.colFmts, rs.colTyps = parsePortalRowDescribe(&rs.rb) + next := parsePortalRowDescribe(&rs.rb) + rs.next = &next return io.EOF default: errorf("unexpected message after execute: %q", t) @@ -1449,10 +1475,16 @@ func (rs *rows) Next(dest []driver.Value) (err error) { } func (rs *rows) HasNextResultSet() bool { - return !rs.done + hasNext := rs.next != nil && !rs.done + return hasNext } func (rs *rows) NextResultSet() error { + if rs.next == nil { + return io.EOF + } + rs.rowsHeader = *rs.next + rs.next = nil return nil } @@ -1475,6 +1507,39 @@ func QuoteIdentifier(name string) string { return `"` + strings.Replace(name, `"`, `""`, -1) + `"` } +// QuoteLiteral quotes a 'literal' (e.g. a parameter, often used to pass literal +// to DDL and other statements that do not accept parameters) to be used as part +// of an SQL statement. For example: +// +// exp_date := pq.QuoteLiteral("2023-01-05 15:00:00Z") +// err := db.Exec(fmt.Sprintf("CREATE ROLE my_user VALID UNTIL %s", exp_date)) +// +// Any single quotes in name will be escaped. Any backslashes (i.e. "\") will be +// replaced by two backslashes (i.e. "\\") and the C-style escape identifier +// that PostgreSQL provides ('E') will be prepended to the string. +func QuoteLiteral(literal string) string { + // This follows the PostgreSQL internal algorithm for handling quoted literals + // from libpq, which can be found in the "PQEscapeStringInternal" function, + // which is found in the libpq/fe-exec.c source file: + // https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c + // + // substitute any single-quotes (') with two single-quotes ('') + literal = strings.Replace(literal, `'`, `''`, -1) + // determine if the string has any backslashes (\) in it. + // if it does, replace any backslashes (\) with two backslashes (\\) + // then, we need to wrap the entire string with a PostgreSQL + // C-style escape. Per how "PQEscapeStringInternal" handles this case, we + // also add a space before the "E" + if strings.Contains(literal, `\`) { + literal = strings.Replace(literal, `\`, `\\`, -1) + literal = ` E'` + literal + `'` + } else { + // otherwise, we can just wrap the literal with a pair of single quotes + literal = `'` + literal + `'` + } + return literal +} + func md5s(s string) string { h := md5.New() h.Write([]byte(s)) @@ -1630,13 +1695,13 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [ } } -func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []fieldDesc) { +func (cn *conn) readPortalDescribeResponse() rowsHeader { t, r := cn.recv1() switch t { case 'T': return parsePortalRowDescribe(r) case 'n': - return nil, nil, nil + return rowsHeader{} case 'E': err := parseError(r) cn.readReadyForQuery() @@ -1742,11 +1807,11 @@ func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDe return } -func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []fieldDesc) { +func parsePortalRowDescribe(r *readBuf) rowsHeader { n := r.int16() - colNames = make([]string, n) - colFmts = make([]format, n) - colTyps = make([]fieldDesc, n) + colNames := make([]string, n) + colFmts := make([]format, n) + colTyps := make([]fieldDesc, n) for i := range colNames { colNames[i] = r.string() r.next(6) @@ -1755,7 +1820,11 @@ func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, co colTyps[i].Mod = r.int32() colFmts[i] = format(r.int16()) } - return + return rowsHeader{ + colNames: colNames, + colFmts: colFmts, + colTyps: colTyps, + } } // parseEnviron tries to mimic some of libpq's environment handling diff --git a/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go index a5254f2b4..0fdd06a61 100644 --- a/vendor/github.com/lib/pq/conn_go18.go +++ b/vendor/github.com/lib/pq/conn_go18.go @@ -1,5 +1,3 @@ -// +build go1.8 - package pq import ( @@ -9,6 +7,7 @@ import ( "fmt" "io" "io/ioutil" + "time" ) // Implement the "QueryerContext" interface @@ -76,13 +75,32 @@ func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, return tx, nil } +func (cn *conn) Ping(ctx context.Context) error { + if finish := cn.watchCancel(ctx); finish != nil { + defer finish() + } + rows, err := cn.simpleQuery("SELECT 'lib/pq ping test';") + if err != nil { + return driver.ErrBadConn // https://golang.org/pkg/database/sql/driver/#Pinger + } + rows.Close() + return nil +} + func (cn *conn) watchCancel(ctx context.Context) func() { if done := ctx.Done(); done != nil { finished := make(chan struct{}) go func() { select { case <-done: - _ = cn.cancel() + // At this point the function level context is canceled, + // so it must not be used for the additional network + // request to cancel the query. + // Create a new context to pass into the dial. + ctxCancel, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + _ = cn.cancel(ctxCancel) finished <- struct{}{} case <-finished: } @@ -97,8 +115,8 @@ func (cn *conn) watchCancel(ctx context.Context) func() { return nil } -func (cn *conn) cancel() error { - c, err := dial(cn.dialer, cn.opts) +func (cn *conn) cancel(ctx context.Context) error { + c, err := dial(ctx, cn.dialer, cn.opts) if err != nil { return err } diff --git a/vendor/github.com/lib/pq/connector.go b/vendor/github.com/lib/pq/connector.go index 9e66eb5df..2f8ced673 100644 --- a/vendor/github.com/lib/pq/connector.go +++ b/vendor/github.com/lib/pq/connector.go @@ -1,10 +1,12 @@ -// +build go1.10 - package pq import ( "context" "database/sql/driver" + "errors" + "fmt" + "os" + "strings" ) // Connector represents a fixed configuration for the pq driver with a given @@ -14,30 +16,95 @@ import ( // // See https://golang.org/pkg/database/sql/driver/#Connector. // See https://golang.org/pkg/database/sql/#OpenDB. -type connector struct { - name string +type Connector struct { + opts values + dialer Dialer } // Connect returns a connection to the database using the fixed configuration // of this Connector. Context is not used. -func (c *connector) Connect(_ context.Context) (driver.Conn, error) { - return (&Driver{}).Open(c.name) +func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { + return c.open(ctx) } // Driver returnst the underlying driver of this Connector. -func (c *connector) Driver() driver.Driver { +func (c *Connector) Driver() driver.Driver { return &Driver{} } -var _ driver.Connector = &connector{} - // NewConnector returns a connector for the pq driver in a fixed configuration -// with the given name. The returned connector can be used to create any number +// with the given dsn. The returned connector can be used to create any number // of equivalent Conn's. The returned connector is intended to be used with // database/sql.OpenDB. // // See https://golang.org/pkg/database/sql/driver/#Connector. // See https://golang.org/pkg/database/sql/#OpenDB. -func NewConnector(name string) (driver.Connector, error) { - return &connector{name: name}, nil +func NewConnector(dsn string) (*Connector, error) { + var err error + o := make(values) + + // A number of defaults are applied here, in this order: + // + // * Very low precedence defaults applied in every situation + // * Environment variables + // * Explicitly passed connection information + o["host"] = "localhost" + o["port"] = "5432" + // N.B.: Extra float digits should be set to 3, but that breaks + // Postgres 8.4 and older, where the max is 2. + o["extra_float_digits"] = "2" + for k, v := range parseEnviron(os.Environ()) { + o[k] = v + } + + if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") { + dsn, err = ParseURL(dsn) + if err != nil { + return nil, err + } + } + + if err := parseOpts(dsn, o); err != nil { + return nil, err + } + + // Use the "fallback" application name if necessary + if fallback, ok := o["fallback_application_name"]; ok { + if _, ok := o["application_name"]; !ok { + o["application_name"] = fallback + } + } + + // We can't work with any client_encoding other than UTF-8 currently. + // However, we have historically allowed the user to set it to UTF-8 + // explicitly, and there's no reason to break such programs, so allow that. + // Note that the "options" setting could also set client_encoding, but + // parsing its value is not worth it. Instead, we always explicitly send + // client_encoding as a separate run-time parameter, which should override + // anything set in options. + if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) { + return nil, errors.New("client_encoding must be absent or 'UTF8'") + } + o["client_encoding"] = "UTF8" + // DateStyle needs a similar treatment. + if datestyle, ok := o["datestyle"]; ok { + if datestyle != "ISO, MDY" { + return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle) + } + } else { + o["datestyle"] = "ISO, MDY" + } + + // If a user is not provided by any other means, the last + // resort is to use the current operating system provided user + // name. + if _, ok := o["user"]; !ok { + u, err := userCurrent() + if err != nil { + return nil, err + } + o["user"] = u + } + + return &Connector{opts: o, dialer: defaultDialer{}}, nil } diff --git a/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go index a1b029713..2a60054e2 100644 --- a/vendor/github.com/lib/pq/doc.go +++ b/vendor/github.com/lib/pq/doc.go @@ -239,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63 bytes by the PostgreSQL server. You can find a complete, working example of Listener usage at -http://godoc.org/github.com/lib/pq/example/listen. +https://godoc.org/github.com/lib/pq/example/listen. */ package pq diff --git a/vendor/github.com/lib/pq/encode.go b/vendor/github.com/lib/pq/encode.go index 3b0d365f2..a6902fae6 100644 --- a/vendor/github.com/lib/pq/encode.go +++ b/vendor/github.com/lib/pq/encode.go @@ -117,11 +117,10 @@ func textDecode(parameterStatus *parameterStatus, s []byte, typ oid.Oid) interfa } return i case oid.T_float4, oid.T_float8: - bits := 64 - if typ == oid.T_float4 { - bits = 32 - } - f, err := strconv.ParseFloat(string(s), bits) + // We always use 64 bit parsing, regardless of whether the input text is for + // a float4 or float8, because clients expect float64s for all float datatypes + // and returning a 32-bit parsed float64 produces lossy results. + f, err := strconv.ParseFloat(string(s), 64) if err != nil { errorf("%s", err) } diff --git a/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go index 96aae29c6..3d66ba7c5 100644 --- a/vendor/github.com/lib/pq/error.go +++ b/vendor/github.com/lib/pq/error.go @@ -478,13 +478,13 @@ func errRecoverNoErrBadConn(err *error) { } } -func (c *conn) errRecover(err *error) { +func (cn *conn) errRecover(err *error) { e := recover() switch v := e.(type) { case nil: // Do nothing case runtime.Error: - c.bad = true + cn.bad = true panic(v) case *Error: if v.Fatal() { @@ -493,7 +493,7 @@ func (c *conn) errRecover(err *error) { *err = v } case *net.OpError: - c.bad = true + cn.bad = true *err = v case error: if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { @@ -503,13 +503,13 @@ func (c *conn) errRecover(err *error) { } default: - c.bad = true + cn.bad = true panic(fmt.Sprintf("unknown error: %#v", e)) } // Any time we return ErrBadConn, we need to remember it since *Tx doesn't // mark the connection bad in database/sql. if *err == driver.ErrBadConn { - c.bad = true + cn.bad = true } } diff --git a/vendor/github.com/lib/pq/oid/gen.go b/vendor/github.com/lib/pq/oid/gen.go new file mode 100644 index 000000000..7c634cdc5 --- /dev/null +++ b/vendor/github.com/lib/pq/oid/gen.go @@ -0,0 +1,93 @@ +// +build ignore + +// Generate the table of OID values +// Run with 'go run gen.go'. +package main + +import ( + "database/sql" + "fmt" + "log" + "os" + "os/exec" + "strings" + + _ "github.com/lib/pq" +) + +// OID represent a postgres Object Identifier Type. +type OID struct { + ID int + Type string +} + +// Name returns an upper case version of the oid type. +func (o OID) Name() string { + return strings.ToUpper(o.Type) +} + +func main() { + datname := os.Getenv("PGDATABASE") + sslmode := os.Getenv("PGSSLMODE") + + if datname == "" { + os.Setenv("PGDATABASE", "pqgotest") + } + + if sslmode == "" { + os.Setenv("PGSSLMODE", "disable") + } + + db, err := sql.Open("postgres", "") + if err != nil { + log.Fatal(err) + } + rows, err := db.Query(` + SELECT typname, oid + FROM pg_type WHERE oid < 10000 + ORDER BY oid; + `) + if err != nil { + log.Fatal(err) + } + oids := make([]*OID, 0) + for rows.Next() { + var oid OID + if err = rows.Scan(&oid.Type, &oid.ID); err != nil { + log.Fatal(err) + } + oids = append(oids, &oid) + } + if err = rows.Err(); err != nil { + log.Fatal(err) + } + cmd := exec.Command("gofmt") + cmd.Stderr = os.Stderr + w, err := cmd.StdinPipe() + if err != nil { + log.Fatal(err) + } + f, err := os.Create("types.go") + if err != nil { + log.Fatal(err) + } + cmd.Stdout = f + err = cmd.Start() + if err != nil { + log.Fatal(err) + } + fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.") + fmt.Fprintln(w, "\npackage oid") + fmt.Fprintln(w, "const (") + for _, oid := range oids { + fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID) + } + fmt.Fprintln(w, ")") + fmt.Fprintln(w, "var TypeName = map[Oid]string{") + for _, oid := range oids { + fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name()) + } + fmt.Fprintln(w, "}") + w.Close() + cmd.Wait() +} diff --git a/vendor/github.com/lib/pq/scram/scram.go b/vendor/github.com/lib/pq/scram/scram.go new file mode 100644 index 000000000..484f378a7 --- /dev/null +++ b/vendor/github.com/lib/pq/scram/scram.go @@ -0,0 +1,264 @@ +// Copyright (c) 2014 - Gustavo Niemeyer +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Package scram implements a SCRAM-{SHA-1,etc} client per RFC5802. +// +// http://tools.ietf.org/html/rfc5802 +// +package scram + +import ( + "bytes" + "crypto/hmac" + "crypto/rand" + "encoding/base64" + "fmt" + "hash" + "strconv" + "strings" +) + +// Client implements a SCRAM-* client (SCRAM-SHA-1, SCRAM-SHA-256, etc). +// +// A Client may be used within a SASL conversation with logic resembling: +// +// var in []byte +// var client = scram.NewClient(sha1.New, user, pass) +// for client.Step(in) { +// out := client.Out() +// // send out to server +// in := serverOut +// } +// if client.Err() != nil { +// // auth failed +// } +// +type Client struct { + newHash func() hash.Hash + + user string + pass string + step int + out bytes.Buffer + err error + + clientNonce []byte + serverNonce []byte + saltedPass []byte + authMsg bytes.Buffer +} + +// NewClient returns a new SCRAM-* client with the provided hash algorithm. +// +// For SCRAM-SHA-256, for example, use: +// +// client := scram.NewClient(sha256.New, user, pass) +// +func NewClient(newHash func() hash.Hash, user, pass string) *Client { + c := &Client{ + newHash: newHash, + user: user, + pass: pass, + } + c.out.Grow(256) + c.authMsg.Grow(256) + return c +} + +// Out returns the data to be sent to the server in the current step. +func (c *Client) Out() []byte { + if c.out.Len() == 0 { + return nil + } + return c.out.Bytes() +} + +// Err returns the error that ocurred, or nil if there were no errors. +func (c *Client) Err() error { + return c.err +} + +// SetNonce sets the client nonce to the provided value. +// If not set, the nonce is generated automatically out of crypto/rand on the first step. +func (c *Client) SetNonce(nonce []byte) { + c.clientNonce = nonce +} + +var escaper = strings.NewReplacer("=", "=3D", ",", "=2C") + +// Step processes the incoming data from the server and makes the +// next round of data for the server available via Client.Out. +// Step returns false if there are no errors and more data is +// still expected. +func (c *Client) Step(in []byte) bool { + c.out.Reset() + if c.step > 2 || c.err != nil { + return false + } + c.step++ + switch c.step { + case 1: + c.err = c.step1(in) + case 2: + c.err = c.step2(in) + case 3: + c.err = c.step3(in) + } + return c.step > 2 || c.err != nil +} + +func (c *Client) step1(in []byte) error { + if len(c.clientNonce) == 0 { + const nonceLen = 16 + buf := make([]byte, nonceLen+b64.EncodedLen(nonceLen)) + if _, err := rand.Read(buf[:nonceLen]); err != nil { + return fmt.Errorf("cannot read random SCRAM-SHA-256 nonce from operating system: %v", err) + } + c.clientNonce = buf[nonceLen:] + b64.Encode(c.clientNonce, buf[:nonceLen]) + } + c.authMsg.WriteString("n=") + escaper.WriteString(&c.authMsg, c.user) + c.authMsg.WriteString(",r=") + c.authMsg.Write(c.clientNonce) + + c.out.WriteString("n,,") + c.out.Write(c.authMsg.Bytes()) + return nil +} + +var b64 = base64.StdEncoding + +func (c *Client) step2(in []byte) error { + c.authMsg.WriteByte(',') + c.authMsg.Write(in) + + fields := bytes.Split(in, []byte(",")) + if len(fields) != 3 { + return fmt.Errorf("expected 3 fields in first SCRAM-SHA-256 server message, got %d: %q", len(fields), in) + } + if !bytes.HasPrefix(fields[0], []byte("r=")) || len(fields[0]) < 2 { + return fmt.Errorf("server sent an invalid SCRAM-SHA-256 nonce: %q", fields[0]) + } + if !bytes.HasPrefix(fields[1], []byte("s=")) || len(fields[1]) < 6 { + return fmt.Errorf("server sent an invalid SCRAM-SHA-256 salt: %q", fields[1]) + } + if !bytes.HasPrefix(fields[2], []byte("i=")) || len(fields[2]) < 6 { + return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2]) + } + + c.serverNonce = fields[0][2:] + if !bytes.HasPrefix(c.serverNonce, c.clientNonce) { + return fmt.Errorf("server SCRAM-SHA-256 nonce is not prefixed by client nonce: got %q, want %q+\"...\"", c.serverNonce, c.clientNonce) + } + + salt := make([]byte, b64.DecodedLen(len(fields[1][2:]))) + n, err := b64.Decode(salt, fields[1][2:]) + if err != nil { + return fmt.Errorf("cannot decode SCRAM-SHA-256 salt sent by server: %q", fields[1]) + } + salt = salt[:n] + iterCount, err := strconv.Atoi(string(fields[2][2:])) + if err != nil { + return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2]) + } + c.saltPassword(salt, iterCount) + + c.authMsg.WriteString(",c=biws,r=") + c.authMsg.Write(c.serverNonce) + + c.out.WriteString("c=biws,r=") + c.out.Write(c.serverNonce) + c.out.WriteString(",p=") + c.out.Write(c.clientProof()) + return nil +} + +func (c *Client) step3(in []byte) error { + var isv, ise bool + var fields = bytes.Split(in, []byte(",")) + if len(fields) == 1 { + isv = bytes.HasPrefix(fields[0], []byte("v=")) + ise = bytes.HasPrefix(fields[0], []byte("e=")) + } + if ise { + return fmt.Errorf("SCRAM-SHA-256 authentication error: %s", fields[0][2:]) + } else if !isv { + return fmt.Errorf("unsupported SCRAM-SHA-256 final message from server: %q", in) + } + if !bytes.Equal(c.serverSignature(), fields[0][2:]) { + return fmt.Errorf("cannot authenticate SCRAM-SHA-256 server signature: %q", fields[0][2:]) + } + return nil +} + +func (c *Client) saltPassword(salt []byte, iterCount int) { + mac := hmac.New(c.newHash, []byte(c.pass)) + mac.Write(salt) + mac.Write([]byte{0, 0, 0, 1}) + ui := mac.Sum(nil) + hi := make([]byte, len(ui)) + copy(hi, ui) + for i := 1; i < iterCount; i++ { + mac.Reset() + mac.Write(ui) + mac.Sum(ui[:0]) + for j, b := range ui { + hi[j] ^= b + } + } + c.saltedPass = hi +} + +func (c *Client) clientProof() []byte { + mac := hmac.New(c.newHash, c.saltedPass) + mac.Write([]byte("Client Key")) + clientKey := mac.Sum(nil) + hash := c.newHash() + hash.Write(clientKey) + storedKey := hash.Sum(nil) + mac = hmac.New(c.newHash, storedKey) + mac.Write(c.authMsg.Bytes()) + clientProof := mac.Sum(nil) + for i, b := range clientKey { + clientProof[i] ^= b + } + clientProof64 := make([]byte, b64.EncodedLen(len(clientProof))) + b64.Encode(clientProof64, clientProof) + return clientProof64 +} + +func (c *Client) serverSignature() []byte { + mac := hmac.New(c.newHash, c.saltedPass) + mac.Write([]byte("Server Key")) + serverKey := mac.Sum(nil) + + mac = hmac.New(c.newHash, serverKey) + mac.Write(c.authMsg.Bytes()) + serverSignature := mac.Sum(nil) + + encoded := make([]byte, b64.EncodedLen(len(serverSignature))) + b64.Encode(encoded, serverSignature) + return encoded +} diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go index e1a326a0d..d90208455 100644 --- a/vendor/github.com/lib/pq/ssl.go +++ b/vendor/github.com/lib/pq/ssl.go @@ -58,7 +58,13 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) { if err != nil { return nil, err } - sslRenegotiation(&tlsConf) + + // Accept renegotiation requests initiated by the backend. + // + // Renegotiation was deprecated then removed from PostgreSQL 9.5, but + // the default configuration of older versions has it enabled. Redshift + // also initiates renegotiations and cannot be reconfigured. + tlsConf.Renegotiation = tls.RenegotiateFreelyAsClient return func(conn net.Conn) (net.Conn, error) { client := tls.Client(conn, &tlsConf) diff --git a/vendor/github.com/lib/pq/ssl_go1.7.go b/vendor/github.com/lib/pq/ssl_go1.7.go deleted file mode 100644 index d7ba43b32..000000000 --- a/vendor/github.com/lib/pq/ssl_go1.7.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build go1.7 - -package pq - -import "crypto/tls" - -// Accept renegotiation requests initiated by the backend. -// -// Renegotiation was deprecated then removed from PostgreSQL 9.5, but -// the default configuration of older versions has it enabled. Redshift -// also initiates renegotiations and cannot be reconfigured. -func sslRenegotiation(conf *tls.Config) { - conf.Renegotiation = tls.RenegotiateFreelyAsClient -} diff --git a/vendor/github.com/lib/pq/ssl_renegotiation.go b/vendor/github.com/lib/pq/ssl_renegotiation.go deleted file mode 100644 index 85ed5e437..000000000 --- a/vendor/github.com/lib/pq/ssl_renegotiation.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !go1.7 - -package pq - -import "crypto/tls" - -// Renegotiation is not supported by crypto/tls until Go 1.7. -func sslRenegotiation(*tls.Config) {} diff --git a/vendor/github.com/libp2p/go-libp2p-peer/.travis.yml b/vendor/github.com/libp2p/go-eventbus/.travis.yml similarity index 97% rename from vendor/github.com/libp2p/go-libp2p-peer/.travis.yml rename to vendor/github.com/libp2p/go-eventbus/.travis.yml index 5163d693f..ba87d9a80 100644 --- a/vendor/github.com/libp2p/go-libp2p-peer/.travis.yml +++ b/vendor/github.com/libp2p/go-eventbus/.travis.yml @@ -4,7 +4,7 @@ os: language: go go: - - 1.11.x + - 1.12.x env: global: diff --git a/vendor/github.com/libp2p/go-eventbus/LICENSE-APACHE b/vendor/github.com/libp2p/go-eventbus/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/LICENSE-APACHE @@ -0,0 +1,5 @@ +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/libp2p/go-libp2p-peer/LICENSE b/vendor/github.com/libp2p/go-eventbus/LICENSE-MIT similarity index 96% rename from vendor/github.com/libp2p/go-libp2p-peer/LICENSE rename to vendor/github.com/libp2p/go-eventbus/LICENSE-MIT index 26100332b..72dc60d84 100644 --- a/vendor/github.com/libp2p/go-libp2p-peer/LICENSE +++ b/vendor/github.com/libp2p/go-eventbus/LICENSE-MIT @@ -1,7 +1,5 @@ The MIT License (MIT) -Copyright (c) 2016 Jeromy Johnson - 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 diff --git a/vendor/github.com/libp2p/go-eventbus/README.md b/vendor/github.com/libp2p/go-eventbus/README.md new file mode 100644 index 000000000..6cd56ac47 --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/README.md @@ -0,0 +1,25 @@ +# go-eventbus + +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) +[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](https://libp2p.io/) +[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) +[![GoDoc](https://godoc.org/github.com/libp2p/go-eventbus?status.svg)](https://godoc.org/github.com/libp2p/go-eventbus) +[![Coverage Status](https://coveralls.io/repos/github/libp2p/go-eventbus/badge.svg?branch=master)](https://coveralls.io/github/libp2p/go-eventbus?branch=master) +[![Build Status](https://travis-ci.com/libp2p/go-eventbus.svg?branch=master)](https://travis-ci.com/libp2p/go-eventbus) +[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) + +> Simple and fast eventbus for type-based local event delivery. + +## Install + +```sh +go get github.com/libp2p/go-eventbus +``` + +## Usage + +Check out the [GoDocs](https://godoc.org/github.com/libp2p/go-eventbus). + +## License + +Dual-licensed under MIT and ASLv2, by way of the [Permissive License Stack](https://protocol.ai/blog/announcing-the-permissive-license-stack/). diff --git a/vendor/github.com/libp2p/go-eventbus/basic.go b/vendor/github.com/libp2p/go-eventbus/basic.go new file mode 100644 index 000000000..0e928832b --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/basic.go @@ -0,0 +1,263 @@ +package eventbus + +import ( + "errors" + "fmt" + "reflect" + "sync" + "sync/atomic" + + "github.com/libp2p/go-libp2p-core/event" +) + +/////////////////////// +// BUS + +// basicBus is a type-based event delivery system +type basicBus struct { + lk sync.Mutex + nodes map[reflect.Type]*node +} + +var _ event.Bus = (*basicBus)(nil) + +type emitter struct { + n *node + typ reflect.Type + closed int32 + dropper func(reflect.Type) +} + +func (e *emitter) Emit(evt interface{}) error { + if atomic.LoadInt32(&e.closed) != 0 { + return fmt.Errorf("emitter is closed") + } + e.n.emit(evt) + return nil +} + +func (e *emitter) Close() error { + if !atomic.CompareAndSwapInt32(&e.closed, 0, 1) { + return fmt.Errorf("closed an emitter more than once") + } + if atomic.AddInt32(&e.n.nEmitters, -1) == 0 { + e.dropper(e.typ) + } + return nil +} + +func NewBus() event.Bus { + return &basicBus{ + nodes: map[reflect.Type]*node{}, + } +} + +func (b *basicBus) withNode(typ reflect.Type, cb func(*node), async func(*node)) { + b.lk.Lock() + + n, ok := b.nodes[typ] + if !ok { + n = newNode(typ) + b.nodes[typ] = n + } + + n.lk.Lock() + b.lk.Unlock() + + cb(n) + + if async == nil { + n.lk.Unlock() + } else { + go func() { + defer n.lk.Unlock() + async(n) + }() + } +} + +func (b *basicBus) tryDropNode(typ reflect.Type) { + b.lk.Lock() + n, ok := b.nodes[typ] + if !ok { // already dropped + b.lk.Unlock() + return + } + + n.lk.Lock() + if atomic.LoadInt32(&n.nEmitters) > 0 || len(n.sinks) > 0 { + n.lk.Unlock() + b.lk.Unlock() + return // still in use + } + n.lk.Unlock() + + delete(b.nodes, typ) + b.lk.Unlock() +} + +type sub struct { + ch chan interface{} + nodes []*node + dropper func(reflect.Type) +} + +func (s *sub) Out() <-chan interface{} { + return s.ch +} + +func (s *sub) Close() error { + go func() { + // drain the event channel, will return when closed and drained. + // this is necessary to unblock publishes to this channel. + for range s.ch { + } + }() + + for _, n := range s.nodes { + n.lk.Lock() + + for i := 0; i < len(n.sinks); i++ { + if n.sinks[i] == s.ch { + n.sinks[i], n.sinks[len(n.sinks)-1] = n.sinks[len(n.sinks)-1], nil + n.sinks = n.sinks[:len(n.sinks)-1] + break + } + } + + tryDrop := len(n.sinks) == 0 && atomic.LoadInt32(&n.nEmitters) == 0 + + n.lk.Unlock() + + if tryDrop { + s.dropper(n.typ) + } + } + close(s.ch) + return nil +} + +var _ event.Subscription = (*sub)(nil) + +// Subscribe creates new subscription. Failing to drain the channel will cause +// publishers to get blocked. CancelFunc is guaranteed to return after last send +// to the channel +func (b *basicBus) Subscribe(evtTypes interface{}, opts ...event.SubscriptionOpt) (_ event.Subscription, err error) { + settings := subSettings(subSettingsDefault) + for _, opt := range opts { + if err := opt(&settings); err != nil { + return nil, err + } + } + + types, ok := evtTypes.([]interface{}) + if !ok { + types = []interface{}{evtTypes} + } + + out := &sub{ + ch: make(chan interface{}, settings.buffer), + nodes: make([]*node, len(types)), + + dropper: b.tryDropNode, + } + + for _, etyp := range types { + if reflect.TypeOf(etyp).Kind() != reflect.Ptr { + return nil, errors.New("subscribe called with non-pointer type") + } + } + + for i, etyp := range types { + typ := reflect.TypeOf(etyp) + + b.withNode(typ.Elem(), func(n *node) { + n.sinks = append(n.sinks, out.ch) + out.nodes[i] = n + }, func(n *node) { + if n.keepLast { + l := n.last + if l == nil { + return + } + out.ch <- l + } + }) + } + + return out, nil +} + +// Emitter creates new emitter +// +// eventType accepts typed nil pointers, and uses the type information to +// select output type +// +// Example: +// emit, err := eventbus.Emitter(new(EventT)) +// defer emit.Close() // MUST call this after being done with the emitter +// +// emit(EventT{}) +func (b *basicBus) Emitter(evtType interface{}, opts ...event.EmitterOpt) (e event.Emitter, err error) { + var settings emitterSettings + + for _, opt := range opts { + if err := opt(&settings); err != nil { + return nil, err + } + } + + typ := reflect.TypeOf(evtType) + if typ.Kind() != reflect.Ptr { + return nil, errors.New("emitter called with non-pointer type") + } + typ = typ.Elem() + + b.withNode(typ, func(n *node) { + atomic.AddInt32(&n.nEmitters, 1) + n.keepLast = n.keepLast || settings.makeStateful + e = &emitter{n: n, typ: typ, dropper: b.tryDropNode} + }, nil) + return +} + +/////////////////////// +// NODE + +type node struct { + // Note: make sure to NEVER lock basicBus.lk when this lock is held + lk sync.Mutex + + typ reflect.Type + + // emitter ref count + nEmitters int32 + + keepLast bool + last interface{} + + sinks []chan interface{} +} + +func newNode(typ reflect.Type) *node { + return &node{ + typ: typ, + } +} + +func (n *node) emit(event interface{}) { + typ := reflect.TypeOf(event) + if typ != n.typ { + panic(fmt.Sprintf("Emit called with wrong type. expected: %s, got: %s", n.typ, typ)) + } + + n.lk.Lock() + if n.keepLast { + n.last = event + } + + for _, ch := range n.sinks { + ch <- event + } + n.lk.Unlock() +} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/codecov.yml b/vendor/github.com/libp2p/go-eventbus/codecov.yml similarity index 100% rename from vendor/github.com/libp2p/go-libp2p-crypto/codecov.yml rename to vendor/github.com/libp2p/go-eventbus/codecov.yml diff --git a/vendor/github.com/libp2p/go-eventbus/go.mod b/vendor/github.com/libp2p/go-eventbus/go.mod new file mode 100644 index 000000000..4dfac97ba --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/go.mod @@ -0,0 +1,8 @@ +module github.com/libp2p/go-eventbus + +go 1.12 + +require ( + github.com/libp2p/go-libp2p-core v0.2.2 + github.com/libp2p/go-libp2p-testing v0.0.4 +) diff --git a/vendor/github.com/libp2p/go-eventbus/go.sum b/vendor/github.com/libp2p/go-eventbus/go.sum new file mode 100644 index 000000000..5925ea36e --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/go.sum @@ -0,0 +1,145 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-eventbus/opts.go b/vendor/github.com/libp2p/go-eventbus/opts.go new file mode 100644 index 000000000..921923500 --- /dev/null +++ b/vendor/github.com/libp2p/go-eventbus/opts.go @@ -0,0 +1,32 @@ +package eventbus + +type subSettings struct { + buffer int +} + +var subSettingsDefault = subSettings{ + buffer: 16, +} + +func BufSize(n int) func(interface{}) error { + return func(s interface{}) error { + s.(*subSettings).buffer = n + return nil + } +} + +type emitterSettings struct { + makeStateful bool +} + +// Stateful is an Emitter option which makes makes the eventbus channel +// 'remember' last event sent, and when a new subscriber joins the +// bus, the remembered event is immediately sent to the subscription +// channel. +// +// This allows to provide state tracking for dynamic systems, and/or +// allows new subscribers to verify that there are Emitters on the channel +func Stateful(s interface{}) error { + s.(*emitterSettings).makeStateful = true + return nil +} diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/conn.go b/vendor/github.com/libp2p/go-libp2p-circuit/conn.go index 8fa53b3da..11f947633 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/conn.go +++ b/vendor/github.com/libp2p/go-libp2p-circuit/conn.go @@ -80,12 +80,15 @@ func (c *Conn) untagHop() { // TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input" func (c *Conn) RemoteMultiaddr() ma.Multiaddr { - proto := ma.ProtocolWithCode(ma.P_P2P).Name - peerid := c.stream.Conn().RemotePeer().Pretty() - p2paddr := ma.StringCast(fmt.Sprintf("/%s/%s", proto, peerid)) - - circaddr := ma.Cast(ma.CodeToVarint(P_CIRCUIT)) - return p2paddr.Encapsulate(circaddr) + // TODO: We should be able to do this directly without converting to/from a string. + relayAddr, err := ma.NewComponent( + ma.ProtocolWithCode(ma.P_P2P).Name, + c.stream.Conn().RemotePeer().Pretty(), + ) + if err != nil { + panic(err) + } + return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) } func (c *Conn) LocalMultiaddr() ma.Multiaddr { diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/dial.go b/vendor/github.com/libp2p/go-libp2p-circuit/dial.go index 6668f3970..1b6e9db0f 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/dial.go +++ b/vendor/github.com/libp2p/go-libp2p-circuit/dial.go @@ -20,28 +20,25 @@ func (d *RelayTransport) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (t } func (r *Relay) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (*Conn, error) { - if !r.Matches(a) { + // split /a/p2p-circuit/b into (/a, /p2p-circuit/b) + relayaddr, destaddr := ma.SplitFunc(a, func(c ma.Component) bool { + return c.Protocol().Code == P_CIRCUIT + }) + + // If the address contained no /p2p-circuit part, the second part is nil. + if destaddr == nil { return nil, fmt.Errorf("%s is not a relay address", a) } - parts := ma.Split(a) - spl := ma.Cast(ma.CodeToVarint(P_CIRCUIT)) - - var relayaddr, destaddr ma.Multiaddr - for i, p := range parts { - if p.Equal(spl) { - relayaddr = ma.Join(parts[:i]...) - destaddr = ma.Join(parts[i+1:]...) - break - } - } + // Strip the /p2p-circuit prefix from the destaddr. + _, destaddr = ma.SplitFirst(destaddr) dinfo := &peer.AddrInfo{ID: p, Addrs: []ma.Multiaddr{}} - if len(destaddr.Bytes()) > 0 { + if destaddr != nil { dinfo.Addrs = append(dinfo.Addrs, destaddr) } - if len(relayaddr.Bytes()) == 0 { + if relayaddr == nil { // unspecific relay address, try dialing using known hop relays return r.tryDialRelays(ctx, *dinfo) } diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/go.mod b/vendor/github.com/libp2p/go-libp2p-circuit/go.mod index c9fb82168..8fbc25d67 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/go.mod +++ b/vendor/github.com/libp2p/go-libp2p-circuit/go.mod @@ -4,10 +4,12 @@ require ( github.com/gogo/protobuf v1.2.1 github.com/ipfs/go-log v0.0.1 github.com/libp2p/go-buffer-pool v0.0.2 - github.com/libp2p/go-libp2p-blankhost v0.1.1 - github.com/libp2p/go-libp2p-core v0.0.1 - github.com/libp2p/go-libp2p-swarm v0.1.0 + github.com/libp2p/go-libp2p-blankhost v0.1.4 + github.com/libp2p/go-libp2p-core v0.2.2 + github.com/libp2p/go-libp2p-swarm v0.2.2 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-net v0.0.1 + github.com/multiformats/go-multiaddr v0.1.1 + github.com/multiformats/go-multiaddr-net v0.1.0 ) + +go 1.12 diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/go.sum b/vendor/github.com/libp2p/go-libp2p-circuit/go.sum index fd879b2b6..fa7c30496 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/go.sum +++ b/vendor/github.com/libp2p/go-libp2p-circuit/go.sum @@ -1,42 +1,63 @@ -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= @@ -48,10 +69,13 @@ github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsj github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -64,41 +88,50 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= -github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= -github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= -github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= -github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= -github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= -github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= -github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= -github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-yamux v0.2.0 h1:TSPZ5cMMz/wdoYsye/wU1TE4G3LDGMoeEN0xgnCKU/I= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= -github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= -github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= @@ -106,20 +139,29 @@ github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA2 github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= -github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= -github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-yamux v1.2.2 h1:s6J6o7+ajoQMjHe7BEnq+EynOj5D2EoG8CuQgL3F2vg= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= @@ -129,17 +171,23 @@ github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0 h1:fkISCUNDb3xIpCcI6BGlPsQE+ywcxzimOsUnHWnrE74= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= -github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -151,20 +199,34 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= @@ -172,36 +234,73 @@ github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg5 github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/listen.go b/vendor/github.com/libp2p/go-libp2p-circuit/listen.go index b00015b56..2f0e60c63 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/listen.go +++ b/vendor/github.com/libp2p/go-libp2p-circuit/listen.go @@ -50,7 +50,7 @@ func (l *RelayListener) Addr() net.Addr { } func (l *RelayListener) Multiaddr() ma.Multiaddr { - return ma.Cast(ma.CodeToVarint(P_CIRCUIT)) + return circuitAddr } func (l *RelayListener) Close() error { diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/relay.go b/vendor/github.com/libp2p/go-libp2p-circuit/relay.go index 1bb7cc0d7..fcb1b5e26 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/relay.go +++ b/vendor/github.com/libp2p/go-libp2p-circuit/relay.go @@ -197,8 +197,9 @@ func (r *Relay) Matches(addr ma.Multiaddr) bool { return err == nil } -func (r *Relay) CanHop(ctx context.Context, id peer.ID) (bool, error) { - s, err := r.host.NewStream(ctx, id, ProtoID) +// Queries a peer for support of hop relay +func CanHop(ctx context.Context, host host.Host, id peer.ID) (bool, error) { + s, err := host.NewStream(ctx, id, ProtoID) if err != nil { return false, err } @@ -233,6 +234,10 @@ func (r *Relay) CanHop(ctx context.Context, id peer.ID) (bool, error) { return msg.GetCode() == pb.CircuitRelay_SUCCESS, nil } +func (r *Relay) CanHop(ctx context.Context, id peer.ID) (bool, error) { + return CanHop(ctx, r.host, id) +} + func (r *Relay) handleNewStream(s network.Stream) { log.Infof("new relay stream from: %s", s.Conn().RemotePeer()) diff --git a/vendor/github.com/libp2p/go-libp2p-circuit/transport.go b/vendor/github.com/libp2p/go-libp2p-circuit/transport.go index 57a65779f..082a61c21 100644 --- a/vendor/github.com/libp2p/go-libp2p-circuit/transport.go +++ b/vendor/github.com/libp2p/go-libp2p-circuit/transport.go @@ -11,18 +11,13 @@ import ( ma "github.com/multiformats/go-multiaddr" ) -const P_CIRCUIT = 290 +// Deprecated: use ma.P_CIRCUIT +const P_CIRCUIT = ma.P_CIRCUIT -var Protocol = ma.Protocol{ - Code: P_CIRCUIT, - Size: 0, - Name: "p2p-circuit", - VCode: ma.CodeToVarint(P_CIRCUIT), -} +// Deprecated: use ma.ProtocolWithCode(P_CIRCUIT) +var Protocol = ma.ProtocolWithCode(P_CIRCUIT) -func init() { - ma.AddProtocol(Protocol) -} +var circuitAddr = ma.Cast(Protocol.VCode) var _ transport.Transport = (*RelayTransport)(nil) diff --git a/vendor/github.com/libp2p/go-libp2p-core/LICENSE-APACHE b/vendor/github.com/libp2p/go-libp2p-core/LICENSE-APACHE new file mode 100644 index 000000000..546514363 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/LICENSE-APACHE @@ -0,0 +1,13 @@ +Copyright 2019. Protocol Labs, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/libp2p/go-libp2p-core/LICENSE-MIT b/vendor/github.com/libp2p/go-libp2p-core/LICENSE-MIT new file mode 100644 index 000000000..ea532a830 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright 2019. Protocol Labs, Inc. + +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/libp2p/go-libp2p-core/crypto/ecdsa.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/ecdsa.go index 58e5d5f5a..9ea769513 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/ecdsa.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/ecdsa.go @@ -115,14 +115,9 @@ func (ePriv *ECDSAPrivateKey) Raw() ([]byte, error) { return x509.MarshalECPrivateKey(ePriv.priv) } -// Equals compares to private keys +// Equals compares two private keys func (ePriv *ECDSAPrivateKey) Equals(o Key) bool { - oPriv, ok := o.(*ECDSAPrivateKey) - if !ok { - return false - } - - return ePriv.priv.D.Cmp(oPriv.priv.D) == 0 + return basicEquals(ePriv, o) } // Sign returns the signature of the input data @@ -155,19 +150,13 @@ func (ePub *ECDSAPublicKey) Type() pb.KeyType { } // Raw returns x509 bytes from a public key -func (ePub ECDSAPublicKey) Raw() ([]byte, error) { +func (ePub *ECDSAPublicKey) Raw() ([]byte, error) { return x509.MarshalPKIXPublicKey(ePub.pub) } // Equals compares to public keys func (ePub *ECDSAPublicKey) Equals(o Key) bool { - oPub, ok := o.(*ECDSAPublicKey) - if !ok { - return false - } - - return ePub.pub.X != nil && ePub.pub.Y != nil && oPub.pub.X != nil && oPub.pub.Y != nil && - 0 == ePub.pub.X.Cmp(oPub.pub.X) && 0 == ePub.pub.Y.Cmp(oPub.pub.Y) + return basicEquals(ePub, o) } // Verify compares data to a signature diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/ed25519.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/ed25519.go index b6e553147..231dadb03 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/ed25519.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/ed25519.go @@ -2,6 +2,7 @@ package crypto import ( "bytes" + "crypto/subtle" "errors" "fmt" "io" @@ -70,7 +71,7 @@ func (k *Ed25519PrivateKey) Equals(o Key) bool { return false } - return bytes.Equal(k.k, edk.k) + return subtle.ConstantTimeCompare(k.k, edk.k) == 1 } // GetPublic returns an ed25519 public key from a private key. @@ -131,7 +132,7 @@ func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) { // Remove the redundant public key. See issue #36. redundantPk := data[ed25519.PrivateKeySize:] pk := data[ed25519.PrivateKeySize-ed25519.PublicKeySize : ed25519.PrivateKeySize] - if !bytes.Equal(pk, redundantPk) { + if subtle.ConstantTimeCompare(pk, redundantPk) == 0 { return nil, errors.New("expected redundant ed25519 public key to be redundant") } diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/key.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/key.go index 50167dbe0..6cd9dc0be 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/key.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/key.go @@ -4,12 +4,12 @@ package crypto import ( - "bytes" "crypto/elliptic" "crypto/hmac" "crypto/rand" "crypto/sha1" "crypto/sha512" + "crypto/subtle" "encoding/base64" "errors" "fmt" @@ -143,6 +143,8 @@ func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { curve = elliptic.P384() case "P-521": curve = elliptic.P521() + default: + return nil, nil, fmt.Errorf("unknown curve name") } priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) @@ -180,7 +182,11 @@ type StretchedKeys struct { } // KeyStretcher returns a set of keys for each party by stretching the shared key. -// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey) +// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey). +// This function accepts the following cipher types: +// - AES-128 +// - AES-256 +// The function will panic upon receiving an unknown cipherType func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) { var cipherKeySize int var ivSize int @@ -191,10 +197,8 @@ func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedK case "AES-256": ivSize = 16 cipherKeySize = 32 - case "Blowfish": - ivSize = 8 - // Note: cypherKeySize arbitrarily selected, needs more thought - cipherKeySize = 32 + default: + panic("Unrecognized cipher, programmer error?") } hmacKeySize := 20 @@ -277,6 +281,12 @@ func UnmarshalPublicKey(data []byte) (PubKey, error) { return nil, err } + return PublicKeyFromProto(pmes) +} + +// PublicKeyFromProto converts an unserialized protobuf PublicKey message +// into its representative object. +func PublicKeyFromProto(pmes *pb.PublicKey) (PubKey, error) { um, ok := PubKeyUnmarshallers[pmes.GetType()] if !ok { return nil, ErrBadKeyType @@ -288,6 +298,17 @@ func UnmarshalPublicKey(data []byte) (PubKey, error) { // MarshalPublicKey converts a public key object into a protobuf serialized // public key func MarshalPublicKey(k PubKey) ([]byte, error) { + pbmes, err := PublicKeyToProto(k) + if err != nil { + return nil, err + } + + return proto.Marshal(pbmes) +} + +// PublicKeyToProto converts a public key object into an unserialized +// protobuf PublicKey message. +func PublicKeyToProto(k PubKey) (*pb.PublicKey, error) { pbmes := new(pb.PublicKey) pbmes.Type = k.Type() data, err := k.Raw() @@ -295,8 +316,7 @@ func MarshalPublicKey(k PubKey) ([]byte, error) { return nil, err } pbmes.Data = data - - return proto.Marshal(pbmes) + return pbmes, nil } // UnmarshalPrivateKey converts a protobuf serialized private key into its @@ -345,7 +365,21 @@ func KeyEqual(k1, k2 Key) bool { return true } - b1, err1 := k1.Bytes() - b2, err2 := k2.Bytes() - return bytes.Equal(b1, b2) && err1 == err2 + return k1.Equals(k2) +} + +func basicEquals(k1, k2 Key) bool { + if k1.Type() != k2.Type() { + return false + } + + a, err := k1.Raw() + if err != nil { + return false + } + b, err := k2.Raw() + if err != nil { + return false + } + return subtle.ConstantTimeCompare(a, b) == 1 } diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/openssl_common.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/openssl_common.go index f235e75f3..2466521c7 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/openssl_common.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/openssl_common.go @@ -5,7 +5,7 @@ package crypto import ( pb "github.com/libp2p/go-libp2p-core/crypto/pb" - openssl "github.com/spacemonkeygo/openssl" + openssl "github.com/libp2p/go-openssl" ) // define these as separate types so we can add more key types later and reuse @@ -61,7 +61,12 @@ func (pk *opensslPublicKey) Raw() ([]byte, error) { // Equals checks whether this key is equal to another func (pk *opensslPublicKey) Equals(k Key) bool { - return KeyEqual(pk, k) + k0, ok := k.(*RsaPublicKey) + if !ok { + return basicEquals(pk, k) + } + + return pk.key.Equal(k0.opensslPublicKey.key) } // Sign returns a signature of the input data @@ -94,5 +99,10 @@ func (sk *opensslPrivateKey) Raw() ([]byte, error) { // Equals checks whether this key is equal to another func (sk *opensslPrivateKey) Equals(k Key) bool { - return KeyEqual(sk, k) + k0, ok := k.(*RsaPrivateKey) + if !ok { + return basicEquals(sk, k) + } + + return sk.key.Equal(k0.opensslPrivateKey.key) } diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_common.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_common.go index d50651f21..c7e305439 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_common.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_common.go @@ -1,10 +1,25 @@ package crypto import ( - "errors" + "fmt" + "os" ) +// WeakRsaKeyEnv is an environment variable which, when set, lowers the +// minimum required bits of RSA keys to 512. This should be used exclusively in +// test situations. +const WeakRsaKeyEnv = "LIBP2P_ALLOW_WEAK_RSA_KEYS" + +var MinRsaKeyBits = 2048 + // ErrRsaKeyTooSmall is returned when trying to generate or parse an RSA key -// that's smaller than 512 bits. Keys need to be larger enough to sign a 256bit -// hash so this is a reasonable absolute minimum. -var ErrRsaKeyTooSmall = errors.New("rsa keys must be >= 512 bits to be useful") +// that's smaller than MinRsaKeyBits bits. In test +var ErrRsaKeyTooSmall error + +func init() { + if _, ok := os.LookupEnv(WeakRsaKeyEnv); ok { + MinRsaKeyBits = 512 + } + + ErrRsaKeyTooSmall = fmt.Errorf("rsa keys must be >= %d bits to be useful", MinRsaKeyBits) +} diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_go.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_go.go index e9813779d..d77499194 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_go.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_go.go @@ -27,7 +27,7 @@ type RsaPublicKey struct { // GenerateRSAKeyPair generates a new rsa private and public key func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) { - if bits < 512 { + if bits < MinRsaKeyBits { return nil, nil, ErrRsaKeyTooSmall } priv, err := rsa.GenerateKey(src, bits) @@ -63,7 +63,13 @@ func (pk *RsaPublicKey) Raw() ([]byte, error) { // Equals checks whether this key is equal to another func (pk *RsaPublicKey) Equals(k Key) bool { - return KeyEqual(pk, k) + // make sure this is an rsa public key + other, ok := (k).(*RsaPublicKey) + if !ok { + return basicEquals(pk, k) + } + + return pk.k.N.Cmp(other.k.N) == 0 && pk.k.E == other.k.E } // Sign returns a signature of the input data @@ -93,7 +99,17 @@ func (sk *RsaPrivateKey) Raw() ([]byte, error) { // Equals checks whether this key is equal to another func (sk *RsaPrivateKey) Equals(k Key) bool { - return KeyEqual(sk, k) + // make sure this is an rsa public key + other, ok := (k).(*RsaPrivateKey) + if !ok { + return basicEquals(sk, k) + } + + a := sk.sk + b := other.sk + + // Don't care about constant time. We're only comparing the public half. + return a.PublicKey.N.Cmp(b.PublicKey.N) == 0 && a.PublicKey.E == b.PublicKey.E } // UnmarshalRsaPrivateKey returns a private key from the input x509 bytes @@ -102,7 +118,7 @@ func UnmarshalRsaPrivateKey(b []byte) (PrivKey, error) { if err != nil { return nil, err } - if sk.N.BitLen() < 512 { + if sk.N.BitLen() < MinRsaKeyBits { return nil, ErrRsaKeyTooSmall } return &RsaPrivateKey{sk: *sk}, nil @@ -118,7 +134,7 @@ func UnmarshalRsaPublicKey(b []byte) (PubKey, error) { if !ok { return nil, errors.New("not actually an rsa public key") } - if pk.N.BitLen() < 512 { + if pk.N.BitLen() < MinRsaKeyBits { return nil, ErrRsaKeyTooSmall } return &RsaPublicKey{*pk}, nil diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_openssl.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_openssl.go index 96c558861..fd9d45104 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_openssl.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/rsa_openssl.go @@ -6,7 +6,7 @@ import ( "errors" "io" - openssl "github.com/spacemonkeygo/openssl" + openssl "github.com/libp2p/go-openssl" ) // RsaPrivateKey is an rsa private key @@ -21,7 +21,7 @@ type RsaPublicKey struct { // GenerateRSAKeyPair generates a new rsa private and public key func GenerateRSAKeyPair(bits int, _ io.Reader) (PrivKey, PubKey, error) { - if bits < 512 { + if bits < MinRsaKeyBits { return nil, nil, ErrRsaKeyTooSmall } diff --git a/vendor/github.com/libp2p/go-libp2p-core/crypto/secp256k1.go b/vendor/github.com/libp2p/go-libp2p-core/crypto/secp256k1.go index d2ac74b99..6e98ea6bf 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/crypto/secp256k1.go +++ b/vendor/github.com/libp2p/go-libp2p-core/crypto/secp256k1.go @@ -66,10 +66,10 @@ func (k *Secp256k1PrivateKey) Raw() ([]byte, error) { func (k *Secp256k1PrivateKey) Equals(o Key) bool { sk, ok := o.(*Secp256k1PrivateKey) if !ok { - return false + return basicEquals(k, o) } - return k.D.Cmp(sk.D) == 0 + return k.GetPublic().Equals(sk.GetPublic()) } // Sign returns a signature from input data @@ -107,7 +107,7 @@ func (k *Secp256k1PublicKey) Raw() ([]byte, error) { func (k *Secp256k1PublicKey) Equals(o Key) bool { sk, ok := o.(*Secp256k1PublicKey) if !ok { - return false + return basicEquals(k, o) } return (*btcec.PublicKey)(k).IsEqual((*btcec.PublicKey)(sk)) diff --git a/vendor/github.com/libp2p/go-libp2p-core/event/bus.go b/vendor/github.com/libp2p/go-libp2p-core/event/bus.go new file mode 100644 index 000000000..9dcf93782 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/event/bus.go @@ -0,0 +1,74 @@ +package event + +import "io" + +// SubscriptionOpt represents a subscriber option. Use the options exposed by the implementation of choice. +type SubscriptionOpt = func(interface{}) error + +// EmitterOpt represents an emitter option. Use the options exposed by the implementation of choice. +type EmitterOpt = func(interface{}) error + +// CancelFunc closes a subscriber. +type CancelFunc = func() + +// Emitter represents an actor that emits events onto the eventbus. +type Emitter interface { + io.Closer + + // Emit emits an event onto the eventbus. If any channel subscribed to the topic is blocked, + // calls to Emit will block. + // + // Calling this function with wrong event type will cause a panic. + Emit(evt interface{}) error +} + +// Subscription represents a subscription to one or multiple event types. +type Subscription interface { + io.Closer + + // Out returns the channel from which to consume events. + Out() <-chan interface{} +} + +// Bus is an interface for a type-based event delivery system. +type Bus interface { + // Subscribe creates a new Subscription. + // + // eventType can be either a pointer to a single event type, or a slice of pointers to + // subscribe to multiple event types at once, under a single subscription (and channel). + // + // Failing to drain the channel may cause publishers to block. + // + // Simple example + // + // sub, err := eventbus.Subscribe(new(EventType)) + // defer sub.Close() + // for e := range sub.Out() { + // event := e.(EventType) // guaranteed safe + // [...] + // } + // + // Multi-type example + // + // sub, err := eventbus.Subscribe([]interface{}{new(EventA), new(EventB)}) + // defer sub.Close() + // for e := range sub.Out() { + // select e.(type): + // case EventA: + // [...] + // case EventB: + // [...] + // } + // } + Subscribe(eventType interface{}, opts ...SubscriptionOpt) (Subscription, error) + + // Emitter creates a new event emitter. + // + // eventType accepts typed nil pointers, and uses the type information for wiring purposes. + // + // Example: + // em, err := eventbus.Emitter(new(EventT)) + // defer em.Close() // MUST call this after being done with the emitter + // em.Emit(EventT{}) + Emitter(eventType interface{}, opts ...EmitterOpt) (Emitter, error) +} diff --git a/vendor/github.com/libp2p/go-libp2p-core/event/doc.go b/vendor/github.com/libp2p/go-libp2p-core/event/doc.go new file mode 100644 index 000000000..3a070f3af --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/event/doc.go @@ -0,0 +1,11 @@ +// Package event contains the abstractions for a local event bus, along with the standard events +// that libp2p subsystems may emit. +// +// Source code is arranged as follows: +// * doc.go: this file. +// * bus.go: abstractions for the event bus. +// * rest: event structs, sensibly categorised in files by entity, and following this naming convention: +// Evt[Entity (noun)][Event (verb past tense / gerund)] +// The past tense is used to convey that something happened, whereas the gerund form of the verb (-ing) +// expresses that a process is in progress. Examples: EvtConnEstablishing, EvtConnEstablished. +package event diff --git a/vendor/github.com/libp2p/go-libp2p-core/event/protocol.go b/vendor/github.com/libp2p/go-libp2p-core/event/protocol.go new file mode 100644 index 000000000..87b4312da --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/event/protocol.go @@ -0,0 +1,26 @@ +package event + +import ( + peer "github.com/libp2p/go-libp2p-core/peer" + protocol "github.com/libp2p/go-libp2p-core/protocol" +) + +// EvtPeerProtocolsUpdated should be emitted when a peer we're connected to adds or removes protocols from their stack. +type EvtPeerProtocolsUpdated struct { + // Peer is the peer whose protocols were updated. + Peer peer.ID + // Added enumerates the protocols that were added by this peer. + Added []protocol.ID + // Removed enumerates the protocols that were removed by this peer. + Removed []protocol.ID +} + +// EvtLocalProtocolsUpdated should be emitted when stream handlers are attached or detached from the local host. +// For handlers attached with a matcher predicate (host.SetStreamHandlerMatch()), only the protocol ID will be +// included in this event. +type EvtLocalProtocolsUpdated struct { + // Added enumerates the protocols that were added locally. + Added []protocol.ID + // Removed enumerates the protocols that were removed locally. + Removed []protocol.ID +} diff --git a/vendor/github.com/libp2p/go-libp2p-core/host/host.go b/vendor/github.com/libp2p/go-libp2p-core/host/host.go index d4b3c03fd..9aad5e12c 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/host/host.go +++ b/vendor/github.com/libp2p/go-libp2p-core/host/host.go @@ -7,6 +7,7 @@ import ( "context" "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/event" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" @@ -68,4 +69,7 @@ type Host interface { // ConnManager returns this hosts connection manager ConnManager() connmgr.ConnManager + + // EventBus returns the hosts eventbus + EventBus() event.Bus } diff --git a/vendor/github.com/libp2p/go-libp2p-core/metrics/register.go b/vendor/github.com/libp2p/go-libp2p-core/metrics/register.go new file mode 100644 index 000000000..2fbb74bb2 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/metrics/register.go @@ -0,0 +1,70 @@ +package metrics + +import ( + "fmt" + "sync" + + "go.opencensus.io/stats/view" +) + +var registeredViews = map[string][]*view.View{} +var mu = new(sync.Mutex) + +type ErrNamespace struct { + Namespace string +} + +// ErrUnregisteredNamespace is an error for lookup of requested unregistered Namespace +type ErrUnregisteredNamespace ErrNamespace + +func (e ErrUnregisteredNamespace) Error() string { + return fmt.Sprintf("no views found registered under Namespace %s", e.Namespace) +} + +// ErrDuplicateNamespaceRegistration is an error for a Namespace that has already +// registered views +type ErrDuplicateNamespaceRegistration ErrNamespace + +func (e ErrDuplicateNamespaceRegistration) Error() string { + return fmt.Sprintf("duplicate registration of views by Namespace %s", e.Namespace) +} + +// RegisterViews accepts a namespace and a slice of Views, which will be registered +// with opencensus and maintained in the global registered views map +func RegisterViews(namespace string, views ...*view.View) error { + mu.Lock() + defer mu.Unlock() + _, ok := registeredViews[namespace] + if ok { + return ErrDuplicateNamespaceRegistration{Namespace: namespace} + } else { + registeredViews[namespace] = views + } + + return nil +} + +// LookupViews returns all views for a Namespace name. Returns an error if the +// Namespace has not been registered. +func LookupViews(name string) ([]*view.View, error) { + mu.Lock() + defer mu.Unlock() + views, ok := registeredViews[name] + if !ok { + return nil, ErrUnregisteredNamespace{Namespace: name} + } + response := make([]*view.View, len(views)) + copy(response, views) + return response, nil +} + +// AllViews returns all registered views as a single slice +func AllViews() []*view.View { + var views []*view.View + mu.Lock() + defer mu.Unlock() + for _, vs := range registeredViews { + views = append(views, vs...) + } + return views +} diff --git a/vendor/github.com/libp2p/go-libp2p-core/peer/peer.go b/vendor/github.com/libp2p/go-libp2p-core/peer/peer.go index db307ee1e..edef635c3 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/peer/peer.go +++ b/vendor/github.com/libp2p/go-libp2p-core/peer/peer.go @@ -92,7 +92,7 @@ func (id ID) ExtractPublicKey() (ic.PubKey, error) { if err != nil { return nil, err } - if decoded.Code != mh.ID { + if decoded.Code != mh.IDENTITY { return nil, ErrNoPublicKey } pk, err := ic.UnmarshalPublicKey(decoded.Digest) diff --git a/vendor/github.com/libp2p/go-libp2p-core/peerstore/peerstore.go b/vendor/github.com/libp2p/go-libp2p-core/peerstore/peerstore.go index 2e1b64498..7f2c01c9d 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/peerstore/peerstore.go +++ b/vendor/github.com/libp2p/go-libp2p-core/peerstore/peerstore.go @@ -158,5 +158,6 @@ type ProtoBook interface { GetProtocols(peer.ID) ([]string, error) AddProtocols(peer.ID, ...string) error SetProtocols(peer.ID, ...string) error + RemoveProtocols(peer.ID, ...string) error SupportsProtocols(peer.ID, ...string) ([]string, error) } diff --git a/vendor/github.com/libp2p/go-libp2p-core/protocol/id.go b/vendor/github.com/libp2p/go-libp2p-core/protocol/id.go index f7e4a32ba..9df3b5bcf 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/protocol/id.go +++ b/vendor/github.com/libp2p/go-libp2p-core/protocol/id.go @@ -7,3 +7,23 @@ type ID string const ( TestingID ID = "/p2p/_testing" ) + +// ConvertFromStrings is a convenience function that takes a slice of strings and +// converts it to a slice of protocol.ID. +func ConvertFromStrings(ids []string) (res []ID) { + res = make([]ID, 0, len(ids)) + for _, id := range ids { + res = append(res, ID(id)) + } + return res +} + +// ConvertToStrings is a convenience function that takes a slice of protocol.ID and +// converts it to a slice of strings. +func ConvertToStrings(ids []ID) (res []string) { + res = make([]string, 0, len(ids)) + for _, id := range ids { + res = append(res, string(id)) + } + return res +} diff --git a/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/insecure.go b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/insecure.go index 801569cb0..e3670c222 100644 --- a/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/insecure.go +++ b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/insecure.go @@ -5,64 +5,207 @@ package insecure import ( "context" + "fmt" "net" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/sec" + "github.com/libp2p/go-msgio" ci "github.com/libp2p/go-libp2p-core/crypto" + pb "github.com/libp2p/go-libp2p-core/sec/insecure/pb" ) // ID is the multistream-select protocol ID that should be used when identifying // this security transport. -const ID = "/plaintext/1.0.0" +const ID = "/plaintext/2.0.0" // Transport is a no-op stream security transport. It provides no -// security and simply mocks the security and identity methods to -// return peer IDs known ahead of time. +// security and simply mocks the security methods. Identity methods +// return the local peer's ID and private key, and whatever the remote +// peer presents as their ID and public key. +// No authentication of the remote identity is performed. type Transport struct { - id peer.ID + id peer.ID + key ci.PrivKey } // New constructs a new insecure transport. +// Deprecated: use NewWithIdentity instead. func New(id peer.ID) *Transport { return &Transport{ id: id, } } -// LocalPeer returns the transports local peer ID. +// New constructs a new insecure transport. The provided private key +// is stored and returned from LocalPrivateKey to satisfy the +// SecureTransport interface, and the public key is sent to +// remote peers. No security is provided. +func NewWithIdentity(id peer.ID, key ci.PrivKey) *Transport { + return &Transport{ + id: id, + key: key, + } +} + +// LocalPeer returns the transport's local peer ID. func (t *Transport) LocalPeer() peer.ID { return t.id } -// LocalPrivateKey returns nil. This transport is not secure. +// LocalPrivateKey returns the local private key. +// This key is used only for identity generation and provides no security. func (t *Transport) LocalPrivateKey() ci.PrivKey { - return nil + return t.key } // SecureInbound *pretends to secure* an outbound connection to the given peer. +// It sends the local peer's ID and public key, and receives the same from the remote peer. +// No validation is performed as to the authenticity or ownership of the provided public key, +// and the key exchange provides no security. +// +// SecureInbound may fail if the remote peer sends an ID and public key that are inconsistent +// with each other, or if a network error occurs during the ID exchange. func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn) (sec.SecureConn, error) { - return &Conn{ - Conn: insecure, - local: t.id, - }, nil + conn := &Conn{ + Conn: insecure, + local: t.id, + localPrivKey: t.key, + } + + err := conn.runHandshakeSync() + if err != nil { + return nil, err + } + + return conn, nil } // SecureOutbound *pretends to secure* an outbound connection to the given peer. +// It sends the local peer's ID and public key, and receives the same from the remote peer. +// No validation is performed as to the authenticity or ownership of the provided public key, +// and the key exchange provides no security. +// +// SecureOutbound may fail if the remote peer sends an ID and public key that are inconsistent +// with each other, or if the ID sent by the remote peer does not match the one dialed. It may +// also fail if a network error occurs during the ID exchange. func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) { - return &Conn{ - Conn: insecure, - local: t.id, - remote: p, - }, nil + conn := &Conn{ + Conn: insecure, + local: t.id, + localPrivKey: t.key, + } + + err := conn.runHandshakeSync() + if err != nil { + return nil, err + } + + if t.key != nil && p != conn.remote { + return nil, fmt.Errorf("remote peer sent unexpected peer ID. expected=%s received=%s", + p, conn.remote) + } + + return conn, nil } // Conn is the connection type returned by the insecure transport. type Conn struct { net.Conn + local peer.ID remote peer.ID + + localPrivKey ci.PrivKey + remotePubKey ci.PubKey +} + +func makeExchangeMessage(pubkey ci.PubKey) (*pb.Exchange, error) { + keyMsg, err := ci.PublicKeyToProto(pubkey) + if err != nil { + return nil, err + } + id, err := peer.IDFromPublicKey(pubkey) + if err != nil { + return nil, err + } + + return &pb.Exchange{ + Id: []byte(id), + Pubkey: keyMsg, + }, nil +} + +func (ic *Conn) runHandshakeSync() error { + // If we were initialized without keys, behave as in plaintext/1.0.0 (do nothing) + if ic.localPrivKey == nil { + return nil + } + + rw := msgio.NewReadWriter(ic.Conn) + // Generate an Exchange message + msg, err := makeExchangeMessage(ic.localPrivKey.GetPublic()) + if err != nil { + return err + } + + // Send our Exchange and read theirs + remoteMsg, err := readWriteMsg(rw, msg) + if err != nil { + return err + } + + // Pull remote ID and public key from message + remotePubkey, err := ci.PublicKeyFromProto(remoteMsg.Pubkey) + if err != nil { + return err + } + + remoteID, err := peer.IDFromPublicKey(remotePubkey) + if err != nil { + return err + } + + // Validate that ID matches public key + if !remoteID.MatchesPublicKey(remotePubkey) { + calculatedID, _ := peer.IDFromPublicKey(remotePubkey) + return fmt.Errorf("remote peer id does not match public key. id=%s calculated_id=%s", + remoteID, calculatedID) + } + + // Add remote ID and key to conn state + ic.remotePubKey = remotePubkey + ic.remote = remoteID + return nil +} + +// read and write a message at the same time. +func readWriteMsg(c msgio.ReadWriter, out *pb.Exchange) (*pb.Exchange, error) { + outBytes, err := out.Marshal() + if err != nil { + return nil, err + } + wresult := make(chan error) + go func() { + wresult <- c.WriteMsg(outBytes) + }() + + msg, err1 := c.ReadMsg() + + // Always wait for the read to finish. + err2 := <-wresult + + if err1 != nil { + return nil, err1 + } + if err2 != nil { + c.ReleaseMsg(msg) + return nil, err2 + } + inMsg := new(pb.Exchange) + err = inMsg.Unmarshal(msg) + return inMsg, err } // LocalPeer returns the local peer ID. @@ -76,14 +219,15 @@ func (ic *Conn) RemotePeer() peer.ID { return ic.remote } -// RemotePublicKey returns nil. This connection is not secure +// RemotePublicKey returns whatever public key was given by the remote peer. +// Note that no verification of ownership is done, as this connection is not secure. func (ic *Conn) RemotePublicKey() ci.PubKey { - return nil + return ic.remotePubKey } -// LocalPrivateKey returns nil. This connection is not secure. +// LocalPrivateKey returns the private key for the local peer. func (ic *Conn) LocalPrivateKey() ci.PrivKey { - return nil + return ic.localPrivKey } var _ sec.SecureTransport = (*Transport)(nil) diff --git a/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/Makefile b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/Makefile new file mode 100644 index 000000000..4fb825a4b --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/Makefile @@ -0,0 +1,11 @@ +PB = $(wildcard *.proto) +GO = $(PB:.proto=.pb.go) + +all: $(GO) + +%.pb.go: %.proto + protoc --proto_path=$(GOPATH)/src:../../../crypto/pb:. --gogofaster_out=. $< + +clean: + rm -f *.pb.go + rm -f *.go diff --git a/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.pb.go b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.pb.go new file mode 100644 index 000000000..68b12f0c8 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.pb.go @@ -0,0 +1,404 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: plaintext.proto + +package plaintext_pb + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + pb "github.com/libp2p/go-libp2p-core/crypto/pb" + io "io" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Exchange struct { + Id []byte `protobuf:"bytes,1,opt,name=id" json:"id"` + Pubkey *pb.PublicKey `protobuf:"bytes,2,opt,name=pubkey" json:"pubkey,omitempty"` +} + +func (m *Exchange) Reset() { *m = Exchange{} } +func (m *Exchange) String() string { return proto.CompactTextString(m) } +func (*Exchange) ProtoMessage() {} +func (*Exchange) Descriptor() ([]byte, []int) { + return fileDescriptor_aba144f73931b711, []int{0} +} +func (m *Exchange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Exchange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Exchange.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Exchange) XXX_Merge(src proto.Message) { + xxx_messageInfo_Exchange.Merge(m, src) +} +func (m *Exchange) XXX_Size() int { + return m.Size() +} +func (m *Exchange) XXX_DiscardUnknown() { + xxx_messageInfo_Exchange.DiscardUnknown(m) +} + +var xxx_messageInfo_Exchange proto.InternalMessageInfo + +func (m *Exchange) GetId() []byte { + if m != nil { + return m.Id + } + return nil +} + +func (m *Exchange) GetPubkey() *pb.PublicKey { + if m != nil { + return m.Pubkey + } + return nil +} + +func init() { + proto.RegisterType((*Exchange)(nil), "plaintext.pb.Exchange") +} + +func init() { proto.RegisterFile("plaintext.proto", fileDescriptor_aba144f73931b711) } + +var fileDescriptor_aba144f73931b711 = []byte{ + // 187 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0xc8, 0x49, 0xcc, + 0xcc, 0x2b, 0x49, 0xad, 0x28, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x41, 0x12, 0x48, + 0x92, 0x32, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xc9, 0x4c, + 0x2a, 0x30, 0x2a, 0xd0, 0x4f, 0xcf, 0xd7, 0x85, 0xb0, 0x74, 0x93, 0xf3, 0x8b, 0x52, 0xf5, 0x93, + 0x8b, 0x2a, 0x0b, 0x4a, 0xf2, 0xf5, 0x0b, 0x92, 0xa0, 0x2c, 0x88, 0x31, 0x4a, 0x7e, 0x5c, 0x1c, + 0xae, 0x15, 0xc9, 0x19, 0x89, 0x79, 0xe9, 0xa9, 0x42, 0x22, 0x5c, 0x4c, 0x99, 0x29, 0x12, 0x8c, + 0x0a, 0x8c, 0x1a, 0x3c, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x31, 0x65, 0xa6, 0x08, 0xe9, + 0x70, 0xb1, 0x15, 0x94, 0x26, 0x65, 0xa7, 0x56, 0x4a, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x1b, 0x89, + 0xe8, 0xc1, 0x0c, 0x48, 0xd2, 0x0b, 0x28, 0x4d, 0xca, 0xc9, 0x4c, 0xf6, 0x4e, 0xad, 0x0c, 0x82, + 0xaa, 0x71, 0x92, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, + 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x06, 0x40, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x40, 0xde, 0x90, 0x0b, 0xc2, 0x00, 0x00, 0x00, +} + +func (m *Exchange) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Exchange) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Id != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintPlaintext(dAtA, i, uint64(len(m.Id))) + i += copy(dAtA[i:], m.Id) + } + if m.Pubkey != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintPlaintext(dAtA, i, uint64(m.Pubkey.Size())) + n1, err := m.Pubkey.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + return i, nil +} + +func encodeVarintPlaintext(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Exchange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Id != nil { + l = len(m.Id) + n += 1 + l + sovPlaintext(uint64(l)) + } + if m.Pubkey != nil { + l = m.Pubkey.Size() + n += 1 + l + sovPlaintext(uint64(l)) + } + return n +} + +func sovPlaintext(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozPlaintext(x uint64) (n int) { + return sovPlaintext(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Exchange) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlaintext + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Exchange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Exchange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlaintext + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPlaintext + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPlaintext + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = append(m.Id[:0], dAtA[iNdEx:postIndex]...) + if m.Id == nil { + m.Id = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pubkey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlaintext + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPlaintext + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPlaintext + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pubkey == nil { + m.Pubkey = &pb.PublicKey{} + } + if err := m.Pubkey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPlaintext(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPlaintext + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPlaintext + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPlaintext(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPlaintext + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPlaintext + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPlaintext + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthPlaintext + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthPlaintext + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPlaintext + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipPlaintext(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthPlaintext + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthPlaintext = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPlaintext = fmt.Errorf("proto: integer overflow") +) diff --git a/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.proto b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.proto new file mode 100644 index 000000000..1e299df58 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p-core/sec/insecure/pb/plaintext.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; + +package plaintext.pb; + +import "github.com/libp2p/go-libp2p-core/crypto/pb/crypto.proto"; + +message Exchange { + optional bytes id = 1; + optional crypto.pb.PublicKey pubkey = 2; +} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/.gitignore b/vendor/github.com/libp2p/go-libp2p-crypto/.gitignore deleted file mode 100644 index cc53fd51b..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store - -# vim -.swp -*~ -*.swp -*.swo diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/.travis.yml b/vendor/github.com/libp2p/go-libp2p-crypto/.travis.yml deleted file mode 100644 index 97be2f5c8..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -os: - - linux - -language: go - -go: - - 1.11.x - -env: - global: - - BUILD_DEPTYPE=gomod - matrix: - - GOTFLAGS="-race" - - GOTFLAGS="-race -tags=openssl" - -# disable travis install -install: - - true - -script: - - bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh) - - -cache: - directories: - - $GOPATH/pkg/mod - - $HOME/.cache/go-build - -notifications: - email: false diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/README.md b/vendor/github.com/libp2p/go-libp2p-crypto/README.md deleted file mode 100644 index 1d61419be..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# go-libp2p-crypto -[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) -[![GoDoc](https://godoc.org/github.com/libp2p/go-libp2p-crypto?status.svg)](https://godoc.org/github.com/ipfs/go-libp2p-crypto) -[![Build Status](https://travis-ci.org/libp2p/go-libp2p-crypto.svg?branch=master)](https://travis-ci.org/libp2p/go-libp2p-crypto) -[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) - -> Various cryptographic utilities used by ipfs - -## Table of Contents - -- [Install](#install) -- [Usage](#usage) -- [Contribute](#contribute) - - [Want to hack on IPFS?](#want-to-hack-on-ipfs) -- [License](#license) - -## Install - -```sh -go get github.com/libp2p/go-libp2p-crypto -``` - -## Usage - -Go to https://godoc.org/github.com/libp2p/go-libp2p-crypto. - -## Contribute - -Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/go-libp2p-crypto/issues)! - -Check out our [contributing document](https://github.com/libp2p/community/blob/master/CONTRIBUTE.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to libp2p are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - -Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. - -## License - -[MIT](LICENSE) © 2016 Jeromy Johnson - ---- - -The last gx published version of this module was: 2.0.7: QmTW4SdgBWq9GjsBsHeUx8WuGxzhgzAf88UMH2w62PC8yK diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/ecdsa_deprecated.go b/vendor/github.com/libp2p/go-libp2p-crypto/ecdsa_deprecated.go deleted file mode 100644 index f37d66184..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/ecdsa_deprecated.go +++ /dev/null @@ -1,64 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "io" - - core "github.com/libp2p/go-libp2p-core/crypto" -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSAPrivateKey instead. -type ECDSAPrivateKey = core.ECDSAPrivateKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSAPublicKey instead. -type ECDSAPublicKey = core.ECDSAPublicKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSASig instead. -type ECDSASig = core.ECDSASig - -var ( - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ErrNotECDSAPubKey instead. - ErrNotECDSAPubKey = core.ErrNotECDSAPubKey - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ErrNilSig instead. - ErrNilSig = core.ErrNilSig - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ErrNilPrivateKey instead. - ErrNilPrivateKey = core.ErrNilPrivateKey - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSACurve instead. - ECDSACurve = core.ECDSACurve -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateECDSAKeyPair instead. -func GenerateECDSAKeyPair(src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateECDSAKeyPair(src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateECDSAKeyPairWithCurve instead. -func GenerateECDSAKeyPairWithCurve(curve elliptic.Curve, src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateECDSAKeyPairWithCurve(curve, src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSAKeyPairFromKey instead. -func ECDSAKeyPairFromKey(priv *ecdsa.PrivateKey) (PrivKey, PubKey, error) { - return core.ECDSAKeyPairFromKey(priv) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.MarshalECDSAPrivateKey instead. -func MarshalECDSAPrivateKey(ePriv ECDSAPrivateKey) ([]byte, error) { - return core.MarshalECDSAPrivateKey(ePriv) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.MarshalECDSAPublicKey instead. -func MarshalECDSAPublicKey(ePub ECDSAPublicKey) ([]byte, error) { - return core.MarshalECDSAPublicKey(ePub) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalECDSAPrivateKey instead. -func UnmarshalECDSAPrivateKey(data []byte) (PrivKey, error) { - return core.UnmarshalECDSAPrivateKey(data) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalECDSAPublicKey instead. -func UnmarshalECDSAPublicKey(data []byte) (PubKey, error) { - return core.UnmarshalECDSAPublicKey(data) -} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/ed25519_deprecated.go b/vendor/github.com/libp2p/go-libp2p-crypto/ed25519_deprecated.go deleted file mode 100644 index 3d9a4b472..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/ed25519_deprecated.go +++ /dev/null @@ -1,28 +0,0 @@ -package crypto - -import ( - "io" - - core "github.com/libp2p/go-libp2p-core/crypto" -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Ed25519PrivateKey instead. -type Ed25519PrivateKey = core.Ed25519PrivateKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Ed25519PublicKey instead. -type Ed25519PublicKey = core.Ed25519PublicKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateEd25519Key instead. -func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateEd25519Key(src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalEd25519PublicKey instead. -func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) { - return core.UnmarshalEd25519PublicKey(data) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalEd25519PrivateKey instead. -func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) { - return core.UnmarshalEd25519PrivateKey(data) -} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/go.mod b/vendor/github.com/libp2p/go-libp2p-crypto/go.mod deleted file mode 100644 index 38a007aba..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/libp2p/go-libp2p-crypto - -require github.com/libp2p/go-libp2p-core v0.0.1 diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/go.sum b/vendor/github.com/libp2p/go-libp2p-crypto/go.sum deleted file mode 100644 index 669c03518..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/go.sum +++ /dev/null @@ -1,67 +0,0 @@ -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1 h1:OJIdWOWYe2l5PQNgimGtuwHY8nDskvJ5vvs//YnzRLs= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/key_deprecated.go b/vendor/github.com/libp2p/go-libp2p-crypto/key_deprecated.go deleted file mode 100644 index 573426900..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/key_deprecated.go +++ /dev/null @@ -1,108 +0,0 @@ -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto instead. -package crypto - -import ( - "io" - - core "github.com/libp2p/go-libp2p-core/crypto" -) - -const ( - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.RSA instead. - RSA = core.RSA - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Ed25519 instead. - Ed25519 = core.Ed25519 - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Secp256k1 instead. - Secp256k1 = core.Secp256k1 - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ECDSA instead. - ECDSA = core.ECDSA -) - -var ( - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ErrBadKeyType instead. - ErrBadKeyType = core.ErrBadKeyType - // Deprecated: use github.com/libp2p/go-libp2p-core/crypto.KeyTypes instead. - KeyTypes = core.KeyTypes -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PubKeyUnmarshaller instead. -type PubKeyUnmarshaller = core.PubKeyUnmarshaller - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PrivKeyUnmarshaller instead. -type PrivKeyUnmarshaller = core.PrivKeyUnmarshaller - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PubKeyUnmarshallers instead. -var PubKeyUnmarshallers = core.PubKeyUnmarshallers - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PrivKeyUnmarshallers instead. -var PrivKeyUnmarshallers = core.PrivKeyUnmarshallers - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Key instead. -type Key = core.Key - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PrivKey instead. -type PrivKey = core.PrivKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.PubKey instead. -type PubKey = core.PubKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenSharedKey instead. -type GenSharedKey = core.GenSharedKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateKeyPair instead. -func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) { - return core.GenerateKeyPair(typ, bits) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateKeyPairWithReader instead. -func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateKeyPairWithReader(typ, bits, src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateEKeyPair instead. -func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { - return core.GenerateEKeyPair(curveName) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenSharedKey instead. -type StretchedKeys = core.StretchedKeys - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.KeyStretcher instead. -func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) { - return core.KeyStretcher(cipherType, hashType, secret) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalPublicKey instead. -func UnmarshalPublicKey(data []byte) (PubKey, error) { - return core.UnmarshalPublicKey(data) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.MarshalPublicKey instead. -func MarshalPublicKey(k PubKey) ([]byte, error) { - return core.MarshalPublicKey(k) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalPrivateKey instead. -func UnmarshalPrivateKey(data []byte) (PrivKey, error) { - return core.UnmarshalPrivateKey(data) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.MarshalPrivateKey instead. -func MarshalPrivateKey(k PrivKey) ([]byte, error) { - return core.MarshalPrivateKey(k) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ConfigDecodeKey instead. -func ConfigDecodeKey(b string) ([]byte, error) { - return core.ConfigDecodeKey(b) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ConfigEncodeKey instead. -func ConfigEncodeKey(b []byte) string { - return core.ConfigEncodeKey(b) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.KeyEqual instead. -func KeyEqual(k1, k2 Key) bool { - return core.KeyEqual(k1, k2) -} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/rsa_deprecated.go b/vendor/github.com/libp2p/go-libp2p-crypto/rsa_deprecated.go deleted file mode 100644 index 8c3e4c4c3..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/rsa_deprecated.go +++ /dev/null @@ -1,31 +0,0 @@ -package crypto - -import ( - "io" - - core "github.com/libp2p/go-libp2p-core/crypto" -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.ErrRsaKeyTooSmall instead. -var ErrRsaKeyTooSmall = core.ErrRsaKeyTooSmall - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.RsaPrivateKey instead. -type RsaPrivateKey = core.RsaPrivateKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.RsaPublicKey instead. -type RsaPublicKey = core.RsaPublicKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateRSAKeyPair instead. -func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateRSAKeyPair(bits, src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalRsaPrivateKey instead. -func UnmarshalRsaPrivateKey(b []byte) (PrivKey, error) { - return core.UnmarshalRsaPrivateKey(b) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalRsaPublicKey instead. -func UnmarshalRsaPublicKey(b []byte) (PubKey, error) { - return core.UnmarshalRsaPublicKey(b) -} diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/secp256k1_deprecated.go b/vendor/github.com/libp2p/go-libp2p-crypto/secp256k1_deprecated.go deleted file mode 100644 index 741321c2a..000000000 --- a/vendor/github.com/libp2p/go-libp2p-crypto/secp256k1_deprecated.go +++ /dev/null @@ -1,28 +0,0 @@ -package crypto - -import ( - "io" - - core "github.com/libp2p/go-libp2p-core/crypto" -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Secp256k1PrivateKey instead. -type Secp256k1PrivateKey = core.Secp256k1PrivateKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.Secp256k1PublicKey instead. -type Secp256k1PublicKey = core.Secp256k1PublicKey - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.GenerateSecp256k1Key instead. -func GenerateSecp256k1Key(src io.Reader) (PrivKey, PubKey, error) { - return core.GenerateSecp256k1Key(src) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalSecp256k1PrivateKey instead. -func UnmarshalSecp256k1PrivateKey(data []byte) (PrivKey, error) { - return core.UnmarshalSecp256k1PrivateKey(data) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/crypto.UnmarshalSecp256k1PublicKey instead. -func UnmarshalSecp256k1PublicKey(data []byte) (PubKey, error) { - return core.UnmarshalSecp256k1PublicKey(data) -} diff --git a/vendor/github.com/libp2p/go-libp2p-peer/README.md b/vendor/github.com/libp2p/go-libp2p-peer/README.md deleted file mode 100644 index ab9b684ed..000000000 --- a/vendor/github.com/libp2p/go-libp2p-peer/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# go-libp2p-peer - -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) -[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23libp2p) -[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](https://libp2p.io/) -[![GoDoc](https://godoc.org/github.com/libp2p/go-libp2p-peer?status.svg)](https://godoc.org/github.com/libp2p/go-libp2p-peer) -[![Coverage Status](https://codecov.io/gh/libp2p/go-libp2p-peer/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-peer/branch/master) -[![Build Status](https://travis-ci.org/libp2p/go-libp2p-peer.svg?branch=master)](https://travis-ci.org/libp2p/go-libp2p-peer) -[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) - -> PKI based identities for use in go-libp2p - -## Install - -TODO - -## Usage - -TODO - -## Contribute - -Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/go-libp2p-peer/issues)! - -This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - -### Want to hack on IPFS? - -[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) - -## License - -MIT - ---- - -The last gx published version of this module was: 3.1.2: QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h diff --git a/vendor/github.com/libp2p/go-libp2p-peer/codecov.yml b/vendor/github.com/libp2p/go-libp2p-peer/codecov.yml deleted file mode 100644 index 5f88a9ea2..000000000 --- a/vendor/github.com/libp2p/go-libp2p-peer/codecov.yml +++ /dev/null @@ -1,3 +0,0 @@ -coverage: - range: "50...100" -comment: off diff --git a/vendor/github.com/libp2p/go-libp2p-peer/deprecated.go b/vendor/github.com/libp2p/go-libp2p-peer/deprecated.go deleted file mode 100644 index 600b5ece1..000000000 --- a/vendor/github.com/libp2p/go-libp2p-peer/deprecated.go +++ /dev/null @@ -1,65 +0,0 @@ -// Deprecated: use github.com/libp2p/go-libp2p-core/peer instead. -package peer - -import ( - core "github.com/libp2p/go-libp2p-core/peer" - ic "github.com/libp2p/go-libp2p-crypto" -) - -var ( - // Deprecated: use github.com/libp2p/go-libp2p-core/peer.ErrEmptyPeerID instead. - ErrEmptyPeerID = core.ErrEmptyPeerID - // Deprecated: use github.com/libp2p/go-libp2p-core/peer.ErrNoPublicKey instead. - ErrNoPublicKey = core.ErrNoPublicKey -) - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.AdvanceEnableInlining instead. -// Warning: this variable's type makes it impossible to alias by reference. -// Reads and writes from/to this variable may be inaccurate or not have the intended effect. -var AdvancedEnableInlining = core.AdvancedEnableInlining - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.ID instead. -type ID = core.ID - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDSlice instead. -type IDSlice = core.IDSlice - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDFromString instead. -func IDFromString(s string) (core.ID, error) { - return core.IDFromString(s) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDFromBytes instead. -func IDFromBytes(b []byte) (core.ID, error) { - return core.IDFromBytes(b) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDB58Decode instead. -func IDB58Decode(s string) (core.ID, error) { - return core.IDB58Decode(s) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDB58Encode instead. -func IDB58Encode(id ID) string { - return core.IDB58Encode(id) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDHexDecode instead. -func IDHexDecode(s string) (core.ID, error) { - return core.IDHexDecode(s) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDHexEncode instead. -func IDHexEncode(id ID) string { - return core.IDHexEncode(id) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDFromPublicKey instead. -func IDFromPublicKey(pk ic.PubKey) (core.ID, error) { - return core.IDFromPublicKey(pk) -} - -// Deprecated: use github.com/libp2p/go-libp2p-core/peer.IDFromPrivateKey instead. -func IDFromPrivateKey(sk ic.PrivKey) (core.ID, error) { - return core.IDFromPrivateKey(sk) -} diff --git a/vendor/github.com/libp2p/go-libp2p-peer/go.mod b/vendor/github.com/libp2p/go-libp2p-peer/go.mod deleted file mode 100644 index c2e26e78c..000000000 --- a/vendor/github.com/libp2p/go-libp2p-peer/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module github.com/libp2p/go-libp2p-peer - -require ( - github.com/libp2p/go-libp2p-core v0.0.1 - github.com/libp2p/go-libp2p-crypto v0.1.0 - golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 // indirect -) diff --git a/vendor/github.com/libp2p/go-libp2p-peer/go.sum b/vendor/github.com/libp2p/go-libp2p-peer/go.sum deleted file mode 100644 index e5bf65d5a..000000000 --- a/vendor/github.com/libp2p/go-libp2p-peer/go.sum +++ /dev/null @@ -1,70 +0,0 @@ -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1 h1:OJIdWOWYe2l5PQNgimGtuwHY8nDskvJ5vvs//YnzRLs= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/go.mod b/vendor/github.com/libp2p/go-libp2p-peerstore/go.mod index 86338f386..65e64f443 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/go.mod +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/go.mod @@ -4,17 +4,15 @@ require ( github.com/gogo/protobuf v1.2.1 github.com/hashicorp/golang-lru v0.5.1 github.com/ipfs/go-datastore v0.0.1 - github.com/ipfs/go-ds-badger v0.0.2 + github.com/ipfs/go-ds-badger v0.0.5 github.com/ipfs/go-ds-leveldb v0.0.1 github.com/ipfs/go-log v0.0.1 github.com/libp2p/go-buffer-pool v0.0.1 - github.com/libp2p/go-libp2p-core v0.0.1 - github.com/libp2p/go-libp2p-crypto v0.1.0 - github.com/libp2p/go-libp2p-peer v0.2.0 + github.com/libp2p/go-libp2p-core v0.0.4 github.com/multiformats/go-base32 v0.0.3 - github.com/multiformats/go-multiaddr v0.0.2 + github.com/multiformats/go-multiaddr v0.0.4 github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/multiformats/go-multihash v0.0.1 + github.com/multiformats/go-multihash v0.0.5 github.com/pkg/errors v0.8.1 github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 github.com/whyrusleeping/mafmt v1.2.8 diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/go.sum b/vendor/github.com/libp2p/go-libp2p-peerstore/go.sum index 6df7a4934..d2caeb049 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/go.sum +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/go.sum @@ -1,25 +1,31 @@ -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f h1:6itBiEUtu+gOzXZWn46bM5/qm8LlV6/byR7Yflx/y6M= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl+LS4Bn3ziLPuEdGRkRjYAbSlWxSA= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0++nN9A= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= @@ -29,8 +35,8 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -41,20 +47,25 @@ github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJ github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-datastore v0.0.1 h1:AW/KZCScnBWlSb5JbnEnLKFWXL224LBEh/9KXXOrUms= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-ds-badger v0.0.2 h1:7ToQt7QByBhOTuZF2USMv+PGlMcBC7FW7FdgQ4FCsoo= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5 h1:dxKuqw5T1Jm8OuV+lchA76H9QZFyPKZeLuT6bN42hJQ= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-leveldb v0.0.1 h1:Z0lsTFciec9qYsyngAw1f/czhRU35qBLR2vhavPFgqA= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -68,12 +79,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= -github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= +github.com/libp2p/go-libp2p-core v0.0.4 h1:wNg7b2tKrZlSNibP+j7A1v8eatjf4+9+YRw0L3DUeFE= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= @@ -82,14 +90,19 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1 h1:OJIdWOWYe2l5PQNgimGtuwHY8nDskvJ5vvs//YnzRLs= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= -github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr-dns v0.0.1 h1:jQt9c6tDSdQLIlBo4tXYx7QUHCPjxsB1zXcag/2S7zc= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= @@ -97,6 +110,8 @@ github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -104,42 +119,67 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= -golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -149,3 +189,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/metrics.go b/vendor/github.com/libp2p/go-libp2p-peerstore/metrics.go index f6d0ccb56..5edfbd48d 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/metrics.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/metrics.go @@ -4,8 +4,8 @@ import ( "sync" "time" - moved "github.com/libp2p/go-libp2p-core/peerstore" - "github.com/libp2p/go-libp2p-peer" + "github.com/libp2p/go-libp2p-core/peer" + core "github.com/libp2p/go-libp2p-core/peerstore" ) // LatencyEWMASmooting governs the decay of the EWMA (the speed @@ -14,7 +14,7 @@ import ( var LatencyEWMASmoothing = 0.1 // Deprecated: use github.com/libp2p/go-libp2p-core/peerstore.Metrics instead. -type Metrics = moved.Metrics +type Metrics = core.Metrics type metrics struct { latmap map[peer.ID]time.Duration diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/peerstore.go b/vendor/github.com/libp2p/go-libp2p-peerstore/peerstore.go index ea29a17fb..3331b4a79 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/peerstore.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/peerstore.go @@ -4,23 +4,24 @@ import ( "fmt" "io" - peer "github.com/libp2p/go-libp2p-peer" + "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) -var _ Peerstore = (*peerstore)(nil) +var _ pstore.Peerstore = (*peerstore)(nil) type peerstore struct { - Metrics + pstore.Metrics - KeyBook - AddrBook - ProtoBook - PeerMetadata + pstore.KeyBook + pstore.AddrBook + pstore.ProtoBook + pstore.PeerMetadata } // NewPeerstore creates a data structure that stores peer data, backed by the // supplied implementations of KeyBook, AddrBook and PeerMetadata. -func NewPeerstore(kb KeyBook, ab AddrBook, pb ProtoBook, md PeerMetadata) Peerstore { +func NewPeerstore(kb pstore.KeyBook, ab pstore.AddrBook, pb pstore.ProtoBook, md pstore.PeerMetadata) pstore.Peerstore { return &peerstore{ KeyBook: kb, AddrBook: ab, @@ -67,22 +68,22 @@ func (ps *peerstore) Peers() peer.IDSlice { return pps } -func (ps *peerstore) PeerInfo(p peer.ID) PeerInfo { - return PeerInfo{ +func (ps *peerstore) PeerInfo(p peer.ID) peer.AddrInfo { + return peer.AddrInfo{ ID: p, Addrs: ps.AddrBook.Addrs(p), } } -func PeerInfos(ps Peerstore, peers peer.IDSlice) []PeerInfo { - pi := make([]PeerInfo, len(peers)) +func PeerInfos(ps pstore.Peerstore, peers peer.IDSlice) []peer.AddrInfo { + pi := make([]peer.AddrInfo, len(peers)) for i, p := range peers { pi[i] = ps.PeerInfo(p) } return pi } -func PeerInfoIDs(pis []PeerInfo) peer.IDSlice { +func PeerInfoIDs(pis []peer.AddrInfo) peer.IDSlice { ps := make(peer.IDSlice, len(pis)) for i, pi := range pis { ps[i] = pi.ID diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/addr_book.go b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/addr_book.go index a497821d0..90ffb175b 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/addr_book.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/addr_book.go @@ -7,10 +7,10 @@ import ( "time" logging "github.com/ipfs/go-log" - peer "github.com/libp2p/go-libp2p-peer" + peer "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" - pstore "github.com/libp2p/go-libp2p-peerstore" + pstore "github.com/libp2p/go-libp2p-core/peerstore" addr "github.com/libp2p/go-libp2p-peerstore/addr" ) @@ -132,7 +132,7 @@ func (mab *memoryAddrBook) AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Durati // AddAddrs gives memoryAddrBook addresses to use, with a given ttl // (time-to-live), after which the address is no longer valid. -// If the manager has a longer TTL, the operation is a no-op for that address +// This function never reduces the TTL or expiration of an address. func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) { // if ttl is zero, exit. nothing to do. if ttl <= 0 { @@ -154,12 +154,21 @@ func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du log.Warningf("was passed nil multiaddr for %s", p) continue } - addrstr := string(addr.Bytes()) - a, found := amap[addrstr] - if !found || exp.After(a.Expires) { - amap[addrstr] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} - + asBytes := addr.Bytes() + a, found := amap[string(asBytes)] // won't allocate. + if !found { + // not found, save and announce it. + amap[string(asBytes)] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} mab.subManager.BroadcastAddr(p, addr) + } else { + // Update expiration/TTL independently. + // We never want to reduce either. + if ttl > a.TTL { + a.TTL = ttl + } + if exp.After(a.Expires) { + a.Expires = exp + } } } } @@ -188,14 +197,14 @@ func (mab *memoryAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du log.Warningf("was passed nil multiaddr for %s", p) continue } - // re-set all of them for new ttl. - addrstr := string(addr.Bytes()) + // re-set all of them for new ttl. + aBytes := addr.Bytes() if ttl > 0 { - amap[addrstr] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} + amap[string(aBytes)] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} mab.subManager.BroadcastAddr(p, addr) } else { - delete(amap, addrstr) + delete(amap, string(aBytes)) } } } diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/keybook.go b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/keybook.go index 87baea24f..f6ab84d23 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/keybook.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/keybook.go @@ -4,10 +4,10 @@ import ( "errors" "sync" - ic "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ic "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) type memoryKeyBook struct { diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/metadata.go b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/metadata.go index 162bee508..821c2b6a5 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/metadata.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/metadata.go @@ -3,10 +3,15 @@ package pstoremem import ( "sync" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) +var internKeys = map[string]bool{ + "AgentVersion": true, + "ProtocolVersion": true, +} + type metakey struct { id peer.ID key string @@ -15,21 +20,30 @@ type metakey struct { type memoryPeerMetadata struct { // store other data, like versions //ds ds.ThreadSafeDatastore - ds map[metakey]interface{} - dslock sync.RWMutex + ds map[metakey]interface{} + dslock sync.RWMutex + interned map[string]interface{} } var _ pstore.PeerMetadata = (*memoryPeerMetadata)(nil) func NewPeerMetadata() pstore.PeerMetadata { return &memoryPeerMetadata{ - ds: make(map[metakey]interface{}), + ds: make(map[metakey]interface{}), + interned: make(map[string]interface{}), } } func (ps *memoryPeerMetadata) Put(p peer.ID, key string, val interface{}) error { ps.dslock.Lock() defer ps.dslock.Unlock() + if vals, ok := val.(string); ok && internKeys[key] { + if interned, ok := ps.interned[vals]; ok { + val = interned + } else { + ps.interned[vals] = val + } + } ps.ds[metakey{p, key}] = val return nil } diff --git a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/protobook.go b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/protobook.go index 04cd14591..d627c6c7b 100644 --- a/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/protobook.go +++ b/vendor/github.com/libp2p/go-libp2p-peerstore/pstoremem/protobook.go @@ -3,14 +3,9 @@ package pstoremem import ( "sync" - peer "github.com/libp2p/go-libp2p-peer" + peer "github.com/libp2p/go-libp2p-core/peer" - pstore "github.com/libp2p/go-libp2p-peerstore" -) - -const ( - maxInternedProtocols = 512 - maxInternedProtocolSize = 256 + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) type protoSegment struct { @@ -35,7 +30,7 @@ var _ pstore.ProtoBook = (*memoryProtoBook)(nil) func NewProtoBook() pstore.ProtoBook { return &memoryProtoBook{ - interned: make(map[string]string, maxInternedProtocols), + interned: make(map[string]string, 256), segments: func() (ret protoSegments) { for i := range ret { ret[i] = &protoSegment{ @@ -48,10 +43,6 @@ func NewProtoBook() pstore.ProtoBook { } func (pb *memoryProtoBook) internProtocol(proto string) string { - if len(proto) > maxInternedProtocolSize { - return proto - } - // check if it is interned with the read lock pb.lk.RLock() interned, ok := pb.interned[proto] @@ -71,11 +62,6 @@ func (pb *memoryProtoBook) internProtocol(proto string) string { return interned } - // if we've filled the table, throw it away and start over - if len(pb.interned) >= maxInternedProtocols { - pb.interned = make(map[string]string, maxInternedProtocols) - } - pb.interned[proto] = proto return proto } @@ -126,6 +112,23 @@ func (pb *memoryProtoBook) GetProtocols(p peer.ID) ([]string, error) { return out, nil } +func (pb *memoryProtoBook) RemoveProtocols(p peer.ID, protos ...string) error { + s := pb.segments.get(p) + s.Lock() + defer s.Unlock() + + protomap, ok := s.protocols[p] + if !ok { + // nothing to remove. + return nil + } + + for _, proto := range protos { + delete(protomap, pb.internProtocol(proto)) + } + return nil +} + func (pb *memoryProtoBook) SupportsProtocols(p peer.ID, protos ...string) ([]string, error) { s := pb.segments.get(p) s.RLock() diff --git a/vendor/github.com/libp2p/go-libp2p-secio/al.go b/vendor/github.com/libp2p/go-libp2p-secio/al.go index 6423f3f2a..8931fec64 100644 --- a/vendor/github.com/libp2p/go-libp2p-secio/al.go +++ b/vendor/github.com/libp2p/go-libp2p-secio/al.go @@ -14,7 +14,6 @@ import ( ci "github.com/libp2p/go-libp2p-core/crypto" sha256 "github.com/minio/sha256-simd" - bfish "golang.org/x/crypto/blowfish" ) // SupportedExchanges is the list of supported ECDH curves @@ -25,7 +24,7 @@ const DefaultSupportedExchanges = "P-256,P-384,P-521" // SupportedCiphers is the list of supported Ciphers var SupportedCiphers = DefaultSupportedCiphers -const DefaultSupportedCiphers = "AES-256,AES-128,Blowfish" +const DefaultSupportedCiphers = "AES-256,AES-128" // SupportedHashes is the list of supported Hashes var SupportedHashes = DefaultSupportedHashes @@ -88,8 +87,6 @@ func newBlockCipher(cipherT string, key []byte) (cipher.Block, error) { switch cipherT { case "AES-128", "AES-256": return aes.NewCipher(key) - case "Blowfish": - return bfish.NewCipher(key) default: return nil, fmt.Errorf("Unrecognized cipher type: %s", cipherT) } diff --git a/vendor/github.com/libp2p/go-libp2p-secio/go.mod b/vendor/github.com/libp2p/go-libp2p-secio/go.mod index 259f7549b..babe1ec66 100644 --- a/vendor/github.com/libp2p/go-libp2p-secio/go.mod +++ b/vendor/github.com/libp2p/go-libp2p-secio/go.mod @@ -6,10 +6,9 @@ require ( github.com/gogo/protobuf v1.2.1 github.com/ipfs/go-log v0.0.1 github.com/libp2p/go-buffer-pool v0.0.2 - github.com/libp2p/go-libp2p-core v0.0.1 + github.com/libp2p/go-libp2p-core v0.2.0 github.com/libp2p/go-libp2p-testing v0.0.2 - github.com/libp2p/go-msgio v0.0.2 + github.com/libp2p/go-msgio v0.0.4 github.com/minio/sha256-simd v0.1.0 github.com/multiformats/go-multihash v0.0.5 - golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f ) diff --git a/vendor/github.com/libp2p/go-libp2p-secio/go.sum b/vendor/github.com/libp2p/go-libp2p-secio/go.sum index 80a4d90cc..25d596b98 100644 --- a/vendor/github.com/libp2p/go-libp2p-secio/go.sum +++ b/vendor/github.com/libp2p/go-libp2p-secio/go.sum @@ -1,50 +1,55 @@ -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= -github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -52,34 +57,23 @@ github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-conn-security v0.0.1 h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs= -github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p-core v0.0.0-20190422125857-3a54eb68d178 h1:+wsyafI3SBZy7fMT8bTdHyrzKnPJfDShnbfjxXM3uqk= -github.com/libp2p/go-libp2p-core v0.0.0-20190422125857-3a54eb68d178/go.mod h1:GYAqGjbAd2HxtkR5D6HsOp1ZPBrGvCD0eCLX8rQtNMw= github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.0.1 h1:JNQd8CmoGTohO/akqrH16ewsqZpci2CbgYH/LmYl8gw= -github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= -github.com/libp2p/go-libp2p-crypto v0.0.2-0.20190422130203-0dad27f616de/go.mod h1:WJ6wEfm4tBdTVrgE7Mle69TjHcAxZArSmhNasnU5HXg= -github.com/libp2p/go-libp2p-net v0.0.1 h1:xJ4Vh4yKF/XKb8fd1Ev0ebAGzVjMxXzrxG2kjtU+F5Q= -github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -github.com/libp2p/go-libp2p-peer v0.0.1 h1:0qwAOljzYewINrU+Kndoc+1jAL7vzY/oY2Go4DCGfyY= -github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= -github.com/libp2p/go-libp2p-peerstore v0.0.1 h1:twKovq8YK5trLrd3nB7PD2Zu9JcyAIdm7Bz9yBWjhq8= -github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM= -github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= +github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= github.com/libp2p/go-libp2p-testing v0.0.2 h1:p9ySW7MFvGGs83hAAe0MPGnjy/tPjl5KyxpMkojdZ+g= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= -github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= -github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= @@ -94,12 +88,10 @@ github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVq github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= @@ -110,50 +102,74 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= -github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-libp2p-secio/protocol.go b/vendor/github.com/libp2p/go-libp2p-secio/protocol.go index 40848ddd6..7ac81af6c 100644 --- a/vendor/github.com/libp2p/go-libp2p-secio/protocol.go +++ b/vendor/github.com/libp2p/go-libp2p-secio/protocol.go @@ -51,8 +51,7 @@ const nonceSize = 16 type secureSession struct { msgio.ReadWriteCloser - insecure net.Conn - insecureM msgio.ReadWriter + insecure net.Conn localKey ci.PrivKey localPeer peer.ID @@ -89,7 +88,6 @@ func newSecureSession(ctx context.Context, local peer.ID, key ci.PrivKey, insecu } s.insecure = insecure - s.insecureM = msgio.NewReadWriter(insecure) s.remotePeer = remotePeer handshakeCtx, cancel := context.WithTimeout(ctx, HandshakeTimeout) // remove @@ -127,15 +125,19 @@ func (s *secureSession) runHandshake(ctx context.Context) error { var err error select { case <-ctx.Done(): + err = ctx.Err() + // State unknown. We *have* to close this. s.insecure.Close() - err = ctx.Err() + // Wait for the handshake to return. + <-result case err = <-result: } return err } func (s *secureSession) runHandshakeSync() error { + insecureM := msgio.NewReadWriter(s.insecure) // ============================================================================= // step 1. Propose -- propose cipher suite + send pubkeys + nonce @@ -170,11 +172,11 @@ func (s *secureSession) runHandshakeSync() error { } // Send Propose packet and Receive their Propose packet - proposeInBytes, err := readWriteMsg(s.insecureM, proposeOutBytes) + proposeInBytes, err := readWriteMsg(insecureM, proposeOutBytes) if err != nil { return err } - defer s.insecureM.ReleaseMsg(proposeInBytes) + defer insecureM.ReleaseMsg(proposeInBytes) // Parse their propose packet proposeIn := new(pb.Propose) @@ -281,11 +283,11 @@ func (s *secureSession) runHandshakeSync() error { } // Send Exchange packet and receive their Exchange packet - exchangeInBytes, err := readWriteMsg(s.insecureM, exchangeOutBytes) + exchangeInBytes, err := readWriteMsg(insecureM, exchangeOutBytes) if err != nil { return err } - defer s.insecureM.ReleaseMsg(exchangeInBytes) + defer insecureM.ReleaseMsg(exchangeInBytes) // Parse their Exchange packet. exchangeIn := new(pb.Exchange) diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/go.mod b/vendor/github.com/libp2p/go-libp2p-swarm/go.mod index 6d3662d98..b7a6825f9 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/go.mod +++ b/vendor/github.com/libp2p/go-libp2p-swarm/go.mod @@ -5,18 +5,20 @@ require ( github.com/jbenet/goprocess v0.1.3 github.com/libp2p/go-addr-util v0.0.1 github.com/libp2p/go-conn-security-multistream v0.1.0 - github.com/libp2p/go-libp2p-core v0.0.1 + github.com/libp2p/go-libp2p-core v0.2.2 github.com/libp2p/go-libp2p-loggables v0.1.0 - github.com/libp2p/go-libp2p-peerstore v0.1.0 - github.com/libp2p/go-libp2p-secio v0.1.0 - github.com/libp2p/go-libp2p-testing v0.0.3 + github.com/libp2p/go-libp2p-peerstore v0.1.3 + github.com/libp2p/go-libp2p-secio v0.2.0 + github.com/libp2p/go-libp2p-testing v0.1.0 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 github.com/libp2p/go-libp2p-yamux v0.2.0 - github.com/libp2p/go-maddr-filter v0.0.4 + github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-stream-muxer-multistream v0.2.0 - github.com/libp2p/go-tcp-transport v0.1.0 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/whyrusleeping/mafmt v1.2.8 + github.com/libp2p/go-tcp-transport v0.1.1 + github.com/multiformats/go-multiaddr v0.1.1 + github.com/multiformats/go-multiaddr-fmt v0.1.0 + github.com/multiformats/go-multiaddr-net v0.1.0 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 ) + +go 1.12 diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/go.sum b/vendor/github.com/libp2p/go-libp2p-swarm/go.sum index 256f3314b..bc852b16f 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/go.sum +++ b/vendor/github.com/libp2p/go-libp2p-swarm/go.sum @@ -1,41 +1,62 @@ -github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= @@ -47,10 +68,13 @@ github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsj github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -67,33 +91,39 @@ github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atq github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= -github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= -github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= -github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= -github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= -github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= -github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-yamux v0.2.0 h1:TSPZ5cMMz/wdoYsye/wU1TE4G3LDGMoeEN0xgnCKU/I= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= -github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= -github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= @@ -101,20 +131,29 @@ github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA2 github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= -github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= -github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= github.com/libp2p/go-yamux v1.2.2 h1:s6J6o7+ajoQMjHe7BEnq+EynOj5D2EoG8CuQgL3F2vg= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= @@ -124,17 +163,22 @@ github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= -github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -146,20 +190,34 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= @@ -167,36 +225,72 @@ github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg5 github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/swarm.go b/vendor/github.com/libp2p/go-libp2p-swarm/swarm.go index b14e9cf0b..5366bdcc6 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/swarm.go +++ b/vendor/github.com/libp2p/go-libp2p-swarm/swarm.go @@ -20,6 +20,7 @@ import ( goprocessctx "github.com/jbenet/goprocess/context" filter "github.com/libp2p/go-maddr-filter" + ma "github.com/multiformats/go-multiaddr" mafilter "github.com/whyrusleeping/multiaddr-filter" ) @@ -58,6 +59,10 @@ type Swarm struct { listeners struct { sync.RWMutex + + ifaceListenAddres []ma.Multiaddr + cacheEOL time.Time + m map[transport.Listener]struct{} } @@ -111,6 +116,11 @@ func NewSwarm(ctx context.Context, local peer.ID, peers peerstore.Peerstore, bwc } func (s *Swarm) teardown() error { + // Wait for the context to be canceled. + // This allows other parts of the swarm to detect that we're shutting + // down. + <-s.ctx.Done() + // Prevents new connections and/or listeners from being added to the swarm. s.listeners.Lock() diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_addr.go b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_addr.go index c86d58bb4..650fb79d1 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_addr.go +++ b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_addr.go @@ -1,6 +1,8 @@ package swarm import ( + "time" + addrutil "github.com/libp2p/go-addr-util" ma "github.com/multiformats/go-multiaddr" ) @@ -9,6 +11,10 @@ import ( func (s *Swarm) ListenAddresses() []ma.Multiaddr { s.listeners.RLock() defer s.listeners.RUnlock() + return s.listenAddressesNoLock() +} + +func (s *Swarm) listenAddressesNoLock() []ma.Multiaddr { addrs := make([]ma.Multiaddr, 0, len(s.listeners.m)) for l := range s.listeners.m { addrs = append(addrs, l.Multiaddr()) @@ -16,9 +22,47 @@ func (s *Swarm) ListenAddresses() []ma.Multiaddr { return addrs } +const ifaceAddrsCacheDuration = 1 * time.Minute + // InterfaceListenAddresses returns a list of addresses at which this swarm // listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to // use the known local interfaces. func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) { - return addrutil.ResolveUnspecifiedAddresses(s.ListenAddresses(), nil) + s.listeners.RLock() // RLock start + + ifaceListenAddres := s.listeners.ifaceListenAddres + isEOL := time.Now().After(s.listeners.cacheEOL) + s.listeners.RUnlock() // RLock end + + if ifaceListenAddres != nil && !isEOL { + // Cache is valid, clone the slice + return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil + } + + // Cache is not valid + // Perfrom double checked locking + + s.listeners.Lock() // Lock start + + ifaceListenAddres = s.listeners.ifaceListenAddres + isEOL = time.Now().After(s.listeners.cacheEOL) + if ifaceListenAddres == nil || isEOL { + // Cache is still invalid + + var err error + ifaceListenAddres, err = addrutil.ResolveUnspecifiedAddresses( + s.listenAddressesNoLock(), nil) + + if err != nil { + s.listeners.Unlock() // Lock early exit + return nil, err + } + + s.listeners.ifaceListenAddres = ifaceListenAddres + s.listeners.cacheEOL = time.Now().Add(ifaceAddrsCacheDuration) + } + + s.listeners.Unlock() // Lock end + + return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil } diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_conn.go b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_conn.go index cdb9866a2..c09957c13 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_conn.go +++ b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_conn.go @@ -122,7 +122,7 @@ func (c *Conn) start() { func (c *Conn) String() string { return fmt.Sprintf( - " %s (%s)>", + " %s (%s)>", c.conn.Transport(), c.conn.LocalMultiaddr(), c.conn.LocalPeer().Pretty(), diff --git a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_listen.go b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_listen.go index 85060c4e2..f1cfa9e7f 100644 --- a/vendor/github.com/libp2p/go-libp2p-swarm/swarm_listen.go +++ b/vendor/github.com/libp2p/go-libp2p-swarm/swarm_listen.go @@ -2,6 +2,7 @@ package swarm import ( "fmt" + "time" "github.com/libp2p/go-libp2p-core/network" @@ -55,6 +56,7 @@ func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { } s.refs.Add(1) s.listeners.m[list] = struct{}{} + s.listeners.cacheEOL = time.Time{} s.listeners.Unlock() maddr := list.Multiaddr() @@ -69,6 +71,7 @@ func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { list.Close() s.listeners.Lock() delete(s.listeners.m, list) + s.listeners.cacheEOL = time.Time{} s.listeners.Unlock() s.refs.Done() }() @@ -76,6 +79,7 @@ func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { c, err := list.Accept() if err != nil { if s.ctx.Err() == nil { + // only log if the swarm is still running. log.Errorf("swarm listener accept error: %s", err) } return @@ -85,9 +89,13 @@ func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { go func() { defer s.refs.Done() _, err := s.addConn(c, network.DirInbound) - if err != nil { - // Probably just means that the swarm has been closed. - log.Warningf("add conn failed: ", err) + switch err { + case nil: + case ErrSwarmClosed: + // ignore. + return + default: + log.Warningf("add conn %s failed: ", err) return } }() diff --git a/vendor/github.com/libp2p/go-libp2p/.travis.yml b/vendor/github.com/libp2p/go-libp2p/.travis.yml index 5163d693f..ba87d9a80 100644 --- a/vendor/github.com/libp2p/go-libp2p/.travis.yml +++ b/vendor/github.com/libp2p/go-libp2p/.travis.yml @@ -4,7 +4,7 @@ os: language: go go: - - 1.11.x + - 1.12.x env: global: diff --git a/vendor/github.com/libp2p/go-libp2p/README.md b/vendor/github.com/libp2p/go-libp2p/README.md index 47ea441d5..a066cd579 100644 --- a/vendor/github.com/libp2p/go-libp2p/README.md +++ b/vendor/github.com/libp2p/go-libp2p/README.md @@ -22,12 +22,6 @@

-# Project status - -[![Throughput Graph](https://graphs.waffle.io/libp2p/go-libp2p/throughput.svg)](https://waffle.io/libp2p/go-libp2p/metrics/throughput) - -[**`Weekly Core Dev Calls`**](https://github.com/ipfs/pm/issues/674) - # Table of Contents - [Background](#background) @@ -40,6 +34,7 @@ - [Tests](#tests) - [Packages](#packages) - [Contribute](#contribute) +- [Weekly Core Dev Calls](https://github.com/ipfs/pm/issues/674) ## Background @@ -58,9 +53,9 @@ libp2p is the product of a long, and arduous quest of understanding -- a deep di ## Usage -This repository (`go-libp2p`) serves as the entrypoint to the universe of modules that compose the Go implementation of the libp2p stack. +This repository (`go-libp2p`) serves as the entrypoint to the universe of modules that compose the Go implementation of the libp2p stack. Libp2p requires go 1.12+. -We mainly use [Go modules](https://github.com/golang/go/wiki/Modules) for our dependency and release management (and thus require go >= 1.11). In order to get the best developer experience, we recommend you do too. Otherwise, you may ocassionally encounter a breaking build as you'll be running off master (which, by definition, is not guaranteed to be stable). +We mainly use [Go modules](https://github.com/golang/go/wiki/Modules) for our dependency and release management (and thus require go >= 1.12+). In order to get the best developer experience, we recommend you do too. Otherwise, you may ocassionally encounter a breaking build as you'll be running off master (which, by definition, is not guaranteed to be stable). You can start using go-libp2p in your Go application simply by adding imports from our repos, e.g.: @@ -116,17 +111,15 @@ If you experience any issues migrating from gx to gomod, please [join the discus List of packages currently in existence for libp2p: -| Name | CI | Coverage | Description | +| Name | CI/Travis | Coverage | Description | | ---------|---------|---------|--------- | | **Libp2p** | | [`go-libp2p`](//github.com/libp2p/go-libp2p) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p) | go-libp2p entry point | -| [`go-libp2p-host`](//github.com/libp2p/go-libp2p-host) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-host.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-host) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-host/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-host) | libp2p "host" interface | +| [`go-libp2p-core`](//github.com/libp2p/go-libp2p-core) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-core.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-core) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-core/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-core) | core interfaces, types, and abstractions | | [`go-libp2p-blankhost`](//github.com/libp2p/go-libp2p-blankhost) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-blankhost.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-blankhost) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-blankhost/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-blankhost) | minimal implementation of the "host" interface | | **Network** | -| [`go-libp2p-net`](//github.com/libp2p/go-libp2p-net) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-net.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-net) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-net/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-net) | libp2p connection and "network" interfaces | -| [`go-libp2p-swarm`](//github.com/libp2p/go-libp2p-swarm) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-swarm.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-swarm) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-swarm/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-swarm) | reference implementation | +| [`go-libp2p-swarm`](//github.com/libp2p/go-libp2p-swarm) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-swarm.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-swarm) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-swarm/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-swarm) | reference implementation of network state machine | | **Transport** | -| [`go-libp2p-transport`](//github.com/libp2p/go-libp2p-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-transport) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-transport) | interfaces | | [`go-ws-transport`](//github.com/libp2p/go-ws-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-ws-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-ws-transport) | [![codecov](https://codecov.io/gh/libp2p/go-ws-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-ws-transport) | WebSocket transport | | [`go-tcp-transport`](//github.com/libp2p/go-tcp-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-tcp-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-tcp-transport) | [![codecov](https://codecov.io/gh/libp2p/go-tcp-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-tcp-transport) | TCP transport | | [`go-libp2p-quic-transport`](//github.com/libp2p/go-libp2p-quic-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-quic-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-quic-transport) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-quic-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-quic-transport) | QUIC transport | @@ -136,28 +129,25 @@ List of packages currently in existence for libp2p: | [`go-libp2p-transport-upgrader`](//github.com/libp2p/go-libp2p-transport-upgrader) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-transport-upgrader.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-transport-upgrader) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-transport-upgrader/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-transport-upgrader) | upgrades multiaddr-net connections into full libp2p transports | | [`go-libp2p-reuseport-transport`](//github.com/libp2p/go-libp2p-reuseport-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-reuseport-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-reuseport-transport) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-reuseport-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-reuseport-transport) | partial transport for building transports that reuse ports | | **Encrypted Channels** | -| [`go-conn-security`](//github.com/libp2p/go-conn-security) | [![Travis CI](https://travis-ci.com/libp2p/go-conn-security.svg?branch=master)](https://travis-ci.com/libp2p/go-conn-security) | [![codecov](https://codecov.io/gh/libp2p/go-conn-security/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-conn-security) | interfaces | | [`go-libp2p-secio`](//github.com/libp2p/go-libp2p-secio) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-secio.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-secio) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-secio/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-secio) | SecIO crypto channel | +| [`go-libp2p-tls`](//github.com/libp2p/go-libp2p-tls) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-tls.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-tls) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-tls/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-tls) | TLS 1.3+ crypto channel | | [`go-conn-security-multistream`](//github.com/libp2p/go-conn-security-multistream) | [![Travis CI](https://travis-ci.com/libp2p/go-conn-security-multistream.svg?branch=master)](https://travis-ci.com/libp2p/go-conn-security-multistream) | [![codecov](https://codecov.io/gh/libp2p/go-conn-security-multistream/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-conn-security-multistream) | multistream multiplexed meta crypto channel | | **Private Network** | -| [`go-libp2p-interface-pnet`](//github.com/libp2p/go-libp2p-interface-pnet) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-interface-pnet.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-interface-pnet) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-interface-pnet/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-interface-pnet) | interfaces | -| [`go-libp2p-pnet`](//github.com/libp2p/go-libp2p-pnet) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-pnet.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-pnet) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-pnet/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-pnet) | reference implementation | +| [`go-libp2p-pnet`](//github.com/libp2p/go-libp2p-pnet) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-pnet.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-pnet) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-pnet/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-pnet) | reference private networking implementation | | **Stream Muxers** | -| [`go-stream-muxer`](//github.com/libp2p/go-stream-muxer) | [![Travis CI](https://travis-ci.com/libp2p/go-stream-muxer.svg?branch=master)](https://travis-ci.com/libp2p/go-stream-muxer) | [![codecov](https://codecov.io/gh/libp2p/go-stream-muxer/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-stream-muxer) | interfaces | -| [`go-smux-yamux`](//github.com/whyrusleeping/go-smux-yamux) | [![Travis CI](https://travis-ci.com/whyrusleeping/go-smux-yamux.svg?branch=master)](https://travis-ci.com/whyrusleeping/go-smux-yamux) | [![codecov](https://codecov.io/gh/whyrusleeping/go-smux-yamux/branch/master/graph/badge.svg)](https://codecov.io/gh/whyrusleeping/go-smux-yamux) | YAMUX stream multiplexer | -| [`go-smux-multiplex`](//github.com/whyrusleeping/go-smux-multiplex) | [![Travis CI](https://travis-ci.com/whyrusleeping/go-smux-multiplex.svg?branch=master)](https://travis-ci.com/whyrusleeping/go-smux-multiplex) | [![codecov](https://codecov.io/gh/whyrusleeping/go-smux-multiplex/branch/master/graph/badge.svg)](https://codecov.io/gh/whyrusleeping/go-smux-multiplex) | MPLEX stream multiplexer | +| [`go-libp2p-yamux`](//github.com/libp2p/go-libp2p-yamux) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-yamux.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-yamux) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-yamux/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-yamux) | YAMUX stream multiplexer | +| [`go-libp2p-mplex`](//github.com/libp2p/go-libp2p-mplex) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-mplex.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-mplex) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-mplex/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-mplex) | MPLEX stream multiplexer | | **NAT Traversal** | | [`go-libp2p-nat`](//github.com/libp2p/go-libp2p-nat) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-nat.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-nat) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-nat/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-nat) | | | **Peerstore** | -| [`go-libp2p-peerstore`](//github.com/libp2p/go-libp2p-peerstore) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-peerstore.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-peerstore) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-peerstore/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-peerstore) | interfaces and reference implementation | +| [`go-libp2p-peerstore`](//github.com/libp2p/go-libp2p-peerstore) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-peerstore.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-peerstore) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-peerstore/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-peerstore) | reference implementation of peer metadata storage component | | **Connection Manager** | -| [`go-libp2p-interface-connmgr`](//github.com/libp2p/go-libp2p-interface-connmgr) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-interface-connmgr.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-interface-connmgr) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-interface-connmgr/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-interface-connmgr) | interface | -| [`go-libp2p-connmgr`](//github.com/libp2p/go-libp2p-connmgr) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-connmgr.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-connmgr) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-connmgr/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-connmgr) | reference implementation | +| [`go-libp2p-connmgr`](//github.com/libp2p/go-libp2p-connmgr) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-connmgr.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-connmgr) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-connmgr/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-connmgr) | reference implementation of connection manager | | **Routing** | -| [`go-libp2p-routing`](//github.com/libp2p/go-libp2p-routing) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-routing.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-routing) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-routing/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-routing) | routing interfaces | | [`go-libp2p-record`](//github.com/libp2p/go-libp2p-record) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-record.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-record) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-record/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-record) | record type and validator logic | -| [`go-libp2p-routing-helpers`](//github.com/libp2p/go-libp2p-routing-helpers) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-routing-helpers.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-routing-helpers) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-routing-helpers/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-routing-helpers) | helpers for composing routers | | [`go-libp2p-kad-dht`](//github.com/libp2p/go-libp2p-kad-dht) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-kad-dht.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-kad-dht) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-kad-dht/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-kad-dht) | Kademlia-like router | +| [`go-libp2p-kbucket`](//github.com/libp2p/go-libp2p-kbucket) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-kbucket.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-kbucket) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-kbucket/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-kbucket) | Kademlia routing table helper types | +| [`go-libp2p-coral-dht`](//github.com/libp2p/go-libp2p-coral-dht) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-coral-dht.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-coral-dht) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-coral-dht/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-coral-dht) | Router based on Coral DHT | | [`go-libp2p-pubsub-router`](//github.com/libp2p/go-libp2p-pubsub-router) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-pubsub-router.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-pubsub-router) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-pubsub-router/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-pubsub-router) | record-store over pubsub adapter | | **Consensus** | | [`go-libp2p-consensus`](//github.com/libp2p/go-libp2p-consensus) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-consensus.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-consensus) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-consensus/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-consensus) | consensus protocols interfaces | @@ -166,13 +156,6 @@ List of packages currently in existence for libp2p: | [`go-libp2p-pubsub`](//github.com/libp2p/go-libp2p-pubsub) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-pubsub.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-pubsub) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-pubsub/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-pubsub) | multiple pubsub over libp2p implementations | | **RPC** | | [`go-libp2p-gorpc`](//github.com/libp2p/go-libp2p-gorpc) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-gorpc.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-gorpc) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-gorpc/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-gorpc) | a simple RPC library for libp2p | -| **Metrics** | -| [`go-libp2p-metrics`](//github.com/libp2p/go-libp2p-metrics) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-metrics.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-metrics) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-metrics/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-metrics) | libp2p metrics interfaces/collectors | -| **Data Types** | -| [`go-libp2p-peer`](//github.com/libp2p/go-libp2p-peer) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-peer.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-peer) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-peer/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-peer) | libp2p peer-ID datatype | -| [`go-libp2p-crypto`](//github.com/libp2p/go-libp2p-crypto) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-crypto.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-crypto) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-crypto/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-crypto) | libp2p key types | -| [`go-libp2p-protocol`](//github.com/libp2p/go-libp2p-protocol) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-protocol.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-protocol) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-protocol/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-protocol) | libp2p protocol datatype | -| [`go-libp2p-kbucket`](//github.com/libp2p/go-libp2p-kbucket) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-kbucket.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-kbucket) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-kbucket/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-kbucket) | Kademlia routing table helper types | | **Utilities/miscellaneous** | | [`go-libp2p-loggables`](//github.com/libp2p/go-libp2p-loggables) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-loggables.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-loggables) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-loggables/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-loggables) | logging helpers | | [`go-maddr-filter`](//github.com/libp2p/go-maddr-filter) | [![Travis CI](https://travis-ci.com/libp2p/go-maddr-filter.svg?branch=master)](https://travis-ci.com/libp2p/go-maddr-filter) | [![codecov](https://codecov.io/gh/libp2p/go-maddr-filter/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-maddr-filter) | multiaddr filtering helpers | @@ -184,10 +167,33 @@ List of packages currently in existence for libp2p: | [`go-reuseport`](//github.com/libp2p/go-reuseport) | [![Travis CI](https://travis-ci.com/libp2p/go-reuseport.svg?branch=master)](https://travis-ci.com/libp2p/go-reuseport) | [![codecov](https://codecov.io/gh/libp2p/go-reuseport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-reuseport) | enables reuse of addresses | | [`go-sockaddr`](//github.com/libp2p/go-sockaddr) | [![Travis CI](https://travis-ci.com/libp2p/go-sockaddr.svg?branch=master)](https://travis-ci.com/libp2p/go-sockaddr) | [![codecov](https://codecov.io/gh/libp2p/go-sockaddr/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-sockaddr) | utils for sockaddr conversions | | [`go-flow-metrics`](//github.com/libp2p/go-flow-metrics) | [![Travis CI](https://travis-ci.com/libp2p/go-flow-metrics.svg?branch=master)](https://travis-ci.com/libp2p/go-flow-metrics) | [![codecov](https://codecov.io/gh/libp2p/go-flow-metrics/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-flow-metrics) | metrics library | +| [`go-libp2p-gostream`](//github.com/libp2p/go-libp2p-gostream) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-gostream.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-gostream) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-gostream/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-gostream) | Go 'net' wrappers for libp2p | +| [`go-libp2p-http`](//github.com/libp2p/go-libp2p-http) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-http.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-http) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-http/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-http) | HTTP on top of libp2p streams | | **Testing and examples** | -| [`go-testutil`](//github.com/libp2p/go-testutil) | [![Travis CI](https://travis-ci.com/libp2p/go-testutil.svg?branch=master)](https://travis-ci.com/libp2p/go-testutil) | [![codecov](https://codecov.io/gh/libp2p/go-testutil/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-testutil) | a collection of testing utilities for ipfs and libp2p | +| [`go-libp2p-testing`](//github.com/libp2p/go-libp2p-testing) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-testing.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-testing) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-testing/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-testing) | a collection of testing utilities for libp2p | | [`go-libp2p-examples`](//github.com/libp2p/go-libp2p-examples) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-examples.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-examples) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-examples/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-examples) | go-libp2p examples and tutorials | +| **Deprecated** | +| [`go-conn-security`](//github.com/libp2p/go-conn-security) | [![Travis CI](https://travis-ci.com/libp2p/go-conn-security.svg?branch=master)](https://travis-ci.com/libp2p/go-conn-security) | [![codecov](https://codecov.io/gh/libp2p/go-conn-security/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-conn-security) | absorbed into go-libp2p-core | +| [`go-peerstream`](//github.com/libp2p/go-peerstream) | [![Travis CI](https://travis-ci.com/libp2p/go-peerstream.svg?branch=master)](https://travis-ci.com/libp2p/go-peerstream) | [![codecov](https://codecov.io/gh/libp2p/go-peerstream/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-peerstream) | early work that informed libp2p design | +| [`go-stream-muxer`](//github.com/libp2p/go-stream-muxer) | [![Travis CI](https://travis-ci.com/libp2p/go-stream-muxer.svg?branch=master)](https://travis-ci.com/libp2p/go-stream-muxer) | [![codecov](https://codecov.io/gh/libp2p/go-stream-muxer/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-stream-muxer) | absorbed into go-libp2p-core | +| [`go-testutil`](//github.com/libp2p/go-testutil) | [![Travis CI](https://travis-ci.com/libp2p/go-testutil.svg?branch=master)](https://travis-ci.com/libp2p/go-testutil) | [![codecov](https://codecov.io/gh/libp2p/go-testutil/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-testutil) | replaced by go-libp2p-testing | | [`go-libp2p-circuit-progs`](//github.com/libp2p/go-libp2p-circuit-progs) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-circuit-progs.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-circuit-progs) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-circuit-progs/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-circuit-progs) | testing programs for go-libp2p-circuit | +| [`go-libp2p-crypto`](//github.com/libp2p/go-libp2p-crypto) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-crypto.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-crypto) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-crypto/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-crypto) | absorbed into go-libp2p-core | +| [`go-libp2p-conn`](//github.com/libp2p/go-libp2p-conn) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-conn.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-conn) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-conn/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-conn) | replaced by go-libp2p-swarm and go-libp2p-transport-upgrader | +| [`go-libp2p-discovery`](//github.com/libp2p/go-libp2p-discovery) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-discovery.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-discovery) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-discovery/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-discovery) | absorbed into go-libp2p-core | +| [`go-libp2p-dummy-conn`](//github.com/libp2p/go-libp2p-dummy-conn) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-dummy-conn.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-dummy-conn) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-dummy-conn/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-dummy-conn) | implempentation of deprecated interface | +| [`go-libp2p-host`](//github.com/libp2p/go-libp2p-host) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-host.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-host) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-host/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-host) | absorbed into go-libp2p-core | +| [`go-libp2p-identify`](//github.com/libp2p/go-libp2p-identify) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-identify.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-identify) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-identify/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-identify) | moved to go-libp2p | +| [`go-libp2p-interface-conn`](//github.com/libp2p/go-libp2p-interface-conn) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-interface-conn.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-interface-conn) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-interface-conn/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-interface-conn) | absorbed into go-libp2p-core | +| [`go-libp2p-interface-connmgr`](//github.com/libp2p/go-libp2p-interface-connmgr) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-interface-connmgr.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-interface-connmgr) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-interface-connmgr/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-interface-connmgr) | absorbed into go-libp2p-core | +| [`go-libp2p-interface-pnet`](//github.com/libp2p/go-libp2p-interface-pnet) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-interface-pnet.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-interface-pnet) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-interface-pnet/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-interface-pnet) | absorbed into go-libp2p-core | +| [`go-libp2p-metrics`](//github.com/libp2p/go-libp2p-metrics) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-metrics.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-metrics) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-metrics/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-metrics) | absorbed into go-libp2p-core | +| [`go-libp2p-net`](//github.com/libp2p/go-libp2p-net) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-net.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-net) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-net/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-net) | absorbed into go-libp2p-core | +| [`go-libp2p-peer`](//github.com/libp2p/go-libp2p-peer) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-peer.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-peer) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-peer/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-peer) | absorbed into go-libp2p-core | +| [`go-libp2p-ping`](//github.com/libp2p/go-libp2p-ping) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-ping.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-ping) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-ping/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-ping) | moved to go-libp2p | +| [`go-libp2p-protocol`](//github.com/libp2p/go-libp2p-protocol) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-protocol.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-protocol) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-protocol/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-protocol) | absorbed into go-libp2p-core | +| [`go-libp2p-transport`](//github.com/libp2p/go-libp2p-transport) | [![Travis CI](https://travis-ci.com/libp2p/go-libp2p-transport.svg?branch=master)](https://travis-ci.com/libp2p/go-libp2p-transport) | [![codecov](https://codecov.io/gh/libp2p/go-libp2p-transport/branch/master/graph/badge.svg)](https://codecov.io/gh/libp2p/go-libp2p-transport) | absorbed into go-libp2p-core | + # Contribute diff --git a/vendor/github.com/libp2p/go-libp2p/config/config.go b/vendor/github.com/libp2p/go-libp2p/config/config.go index 3bb51bf1f..24fc1fa5e 100644 --- a/vendor/github.com/libp2p/go-libp2p/config/config.go +++ b/vendor/github.com/libp2p/go-libp2p/config/config.go @@ -44,6 +44,12 @@ type RoutingC func(host.Host) (routing.PeerRouting, error) // This is *not* a stable interface. Use the options defined in the root // package. type Config struct { + // UserAgent is the identifier this node will send to other peers when + // identifying itself, e.g. via the identify protocol. + // + // Set it via the UserAgent option function. + UserAgent string + PeerKey crypto.PrivKey Transports []TptC @@ -100,13 +106,11 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { return nil, fmt.Errorf("no peerstore specified") } - if !cfg.Insecure { - if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil { - return nil, err - } - if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil { - return nil, err - } + if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil { + return nil, err + } + if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil { + return nil, err } // TODO: Make the swarm implementation configurable. @@ -120,6 +124,7 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { AddrsFactory: cfg.AddrsFactory, NATManager: cfg.NATManager, EnablePing: !cfg.DisablePing, + UserAgent: cfg.UserAgent, }) if err != nil { @@ -142,7 +147,7 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { upgrader.Protector = cfg.Protector upgrader.Filters = swrm.Filters if cfg.Insecure { - upgrader.Secure = makeInsecureTransport(pid) + upgrader.Secure = makeInsecureTransport(pid, cfg.PeerKey) } else { upgrader.Secure, err = makeSecurityTransport(h, cfg.SecurityTransports) if err != nil { diff --git a/vendor/github.com/libp2p/go-libp2p/config/security.go b/vendor/github.com/libp2p/go-libp2p/config/security.go index 8e1c710cb..72d4b0948 100644 --- a/vendor/github.com/libp2p/go-libp2p/config/security.go +++ b/vendor/github.com/libp2p/go-libp2p/config/security.go @@ -3,6 +3,7 @@ package config import ( "fmt" + "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/sec" @@ -49,9 +50,9 @@ func SecurityConstructor(security interface{}) (SecC, error) { }, nil } -func makeInsecureTransport(id peer.ID) sec.SecureTransport { +func makeInsecureTransport(id peer.ID, privKey crypto.PrivKey) sec.SecureTransport { secMuxer := new(csms.SSMuxer) - secMuxer.AddTransport(insecure.ID, insecure.New(id)) + secMuxer.AddTransport(insecure.ID, insecure.NewWithIdentity(id, privKey)) return secMuxer } diff --git a/vendor/github.com/libp2p/go-libp2p/defaults.go b/vendor/github.com/libp2p/go-libp2p/defaults.go index 18de400d9..cdcd8288f 100644 --- a/vendor/github.com/libp2p/go-libp2p/defaults.go +++ b/vendor/github.com/libp2p/go-libp2p/defaults.go @@ -125,7 +125,7 @@ var Defaults Option = func(cfg *Config) error { } // FallbackDefaults applies default options to the libp2p node if and only if no -// other relevent options have been applied. will be appended to the options +// other relevant options have been applied. will be appended to the options // passed into New. var FallbackDefaults Option = func(cfg *Config) error { for _, def := range defaults { diff --git a/vendor/github.com/libp2p/go-libp2p/go.mod b/vendor/github.com/libp2p/go-libp2p/go.mod index d951ad3a1..5f909db54 100644 --- a/vendor/github.com/libp2p/go-libp2p/go.mod +++ b/vendor/github.com/libp2p/go-libp2p/go.mod @@ -1,37 +1,40 @@ module github.com/libp2p/go-libp2p require ( - github.com/gogo/protobuf v1.2.1 - github.com/ipfs/go-cid v0.0.2 + github.com/gogo/protobuf v1.3.0 + github.com/ipfs/go-cid v0.0.3 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-log v0.0.1 github.com/jbenet/go-cienv v0.1.0 github.com/jbenet/goprocess v0.1.3 github.com/libp2p/go-conn-security-multistream v0.1.0 + github.com/libp2p/go-eventbus v0.1.0 github.com/libp2p/go-libp2p-autonat v0.1.0 - github.com/libp2p/go-libp2p-blankhost v0.1.1 - github.com/libp2p/go-libp2p-circuit v0.1.0 - github.com/libp2p/go-libp2p-core v0.0.1 + github.com/libp2p/go-libp2p-blankhost v0.1.4 + github.com/libp2p/go-libp2p-circuit v0.1.3 + github.com/libp2p/go-libp2p-core v0.2.3 github.com/libp2p/go-libp2p-discovery v0.1.0 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.1 github.com/libp2p/go-libp2p-nat v0.0.4 github.com/libp2p/go-libp2p-netutil v0.1.0 - github.com/libp2p/go-libp2p-peerstore v0.1.0 - github.com/libp2p/go-libp2p-secio v0.1.0 - github.com/libp2p/go-libp2p-swarm v0.1.0 - github.com/libp2p/go-libp2p-testing v0.0.4 + github.com/libp2p/go-libp2p-peerstore v0.1.3 + github.com/libp2p/go-libp2p-secio v0.2.0 + github.com/libp2p/go-libp2p-swarm v0.2.2 + github.com/libp2p/go-libp2p-testing v0.1.0 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 github.com/libp2p/go-libp2p-yamux v0.2.1 - github.com/libp2p/go-maddr-filter v0.0.4 + github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-stream-muxer-multistream v0.2.0 - github.com/libp2p/go-tcp-transport v0.1.0 - github.com/libp2p/go-ws-transport v0.1.0 + github.com/libp2p/go-tcp-transport v0.1.1 + github.com/libp2p/go-ws-transport v0.1.2 github.com/miekg/dns v1.1.12 // indirect - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-dns v0.0.2 - github.com/multiformats/go-multiaddr-net v0.0.1 + github.com/multiformats/go-multiaddr v0.1.1 + github.com/multiformats/go-multiaddr-dns v0.1.0 + github.com/multiformats/go-multiaddr-net v0.1.0 github.com/multiformats/go-multistream v0.1.0 - github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30 + github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 ) + +go 1.12 diff --git a/vendor/github.com/libp2p/go-libp2p/go.sum b/vendor/github.com/libp2p/go-libp2p/go.sum index 47c9026ca..90200587e 100644 --- a/vendor/github.com/libp2p/go-libp2p/go.sum +++ b/vendor/github.com/libp2p/go-libp2p/go.sum @@ -1,53 +1,85 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= @@ -67,10 +99,14 @@ github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsj github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -85,17 +121,25 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= -github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= -github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= -github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= -github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= +github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= +github.com/libp2p/go-libp2p-circuit v0.1.3 h1:WsMYYaA0PwdpgJSQu12EzPYf5ypkLSTgcOsWr7DYrgI= +github.com/libp2p/go-libp2p-circuit v0.1.3/go.mod h1:Xqh2TjSy8DD5iV2cCOMzdynd6h8OTBGoV1AWbWor3qM= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.3 h1:zXikZ5pLfebtTMeIYfcwVQ2Pae77O0FIwDquwM6AGNM= +github.com/libp2p/go-libp2p-core v0.2.3/go.mod h1:GqhyQqyIAPsxFYXHMjfXgMv03lxsvM0mFzuYA9Ib42A= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= @@ -108,34 +152,42 @@ github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2 github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= -github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= -github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= +github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXYwAWqHng= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= -github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc= github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= -github.com/libp2p/go-libp2p-yamux v0.2.0 h1:TSPZ5cMMz/wdoYsye/wU1TE4G3LDGMoeEN0xgnCKU/I= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI= github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= -github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= @@ -145,50 +197,70 @@ github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROm github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= -github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= -github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= -github.com/libp2p/go-yamux v1.2.2 h1:s6J6o7+ajoQMjHe7BEnq+EynOj5D2EoG8CuQgL3F2vg= +github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-ws-transport v0.1.2 h1:VnxQcLfSGtqupqPpBNu8fUiCv+IN1RJ2BcVqQEM+z8E= +github.com/libp2p/go-ws-transport v0.1.2/go.mod h1:dsh2Ld8F+XNmzpkaAijmg5Is+e9l6/1tK/6VFOdN69Y= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.1.0 h1:gsPeMvo91XvcsNlQXgJgfjYjbsVV99bvveguUvDBpyQ= +github.com/multiformats/go-multiaddr-dns v0.1.0/go.mod h1:01k2RAqtoXIuPa3DCavAE9/6jc6nM0H3EgZyfUhN2oY= github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -200,20 +272,35 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= @@ -221,44 +308,93 @@ github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL3 github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= -github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30 h1:nMCC9Pwz1pxfC1Y6mYncdk+kq8d5aLx0Q+/gyZGE44M= -github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD21WxrmfeIYCFPuVPRCY2XZTWzTNHGw30= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c h1:vamGzbGri8IKo20MQncCuljcQ5uAO6kaCeawQPVblAI= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-libp2p/options.go b/vendor/github.com/libp2p/go-libp2p/options.go index 6d310f1aa..6463ea712 100644 --- a/vendor/github.com/libp2p/go-libp2p/options.go +++ b/vendor/github.com/libp2p/go-libp2p/options.go @@ -246,7 +246,8 @@ func EnableAutoRelay() Option { } // FilterAddresses configures libp2p to never dial nor accept connections from -// the given addresses. +// the given addresses. FilterAddresses should be used for cases where the +// addresses you want to deny are known ahead of time. func FilterAddresses(addrs ...*net.IPNet) Option { return func(cfg *Config) error { if cfg.Filters == nil { @@ -259,6 +260,17 @@ func FilterAddresses(addrs ...*net.IPNet) Option { } } +// Filters configures libp2p to use the given filters for accepting/denying +// certain addresses. Filters offers more control and should be use when the +// addresses you want to accept/deny are not known ahead of time and can +// dynamically change. +func Filters(filters *filter.Filters) Option { + return func(cfg *Config) error { + cfg.Filters = filters + return nil + } +} + // NATPortMap configures libp2p to use the default NATManager. The default // NATManager will attempt to open a port in your network's firewall using UPnP. func NATPortMap() Option { @@ -319,3 +331,11 @@ var NoTransports = func(cfg *Config) error { cfg.Transports = []config.TptC{} return nil } + +// UserAgent sets the libp2p user-agent sent along with the identify protocol +func UserAgent(userAgent string) Option { + return func(cfg *Config) error { + cfg.UserAgent = userAgent + return nil + } +} diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/host/basic/basic_host.go b/vendor/github.com/libp2p/go-libp2p/p2p/host/basic/basic_host.go index b1d8cbcd4..92946c5d7 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/host/basic/basic_host.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/host/basic/basic_host.go @@ -7,21 +7,24 @@ import ( "sync" "time" + "github.com/libp2p/go-libp2p/p2p/protocol/identify" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" + "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/event" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" "github.com/libp2p/go-libp2p-core/protocol" - logging "github.com/ipfs/go-log" - goprocess "github.com/jbenet/goprocess" - goprocessctx "github.com/jbenet/goprocess/context" - + "github.com/libp2p/go-eventbus" inat "github.com/libp2p/go-libp2p-nat" - identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" - ping "github.com/libp2p/go-libp2p/p2p/protocol/ping" + logging "github.com/ipfs/go-log" + "github.com/jbenet/goprocess" + goprocessctx "github.com/jbenet/goprocess/context" + ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" manet "github.com/multiformats/go-multiaddr-net" @@ -69,6 +72,7 @@ type BasicHost struct { natmgr NATManager maResolver *madns.Resolver cmgr connmgr.ConnManager + eventbus event.Bus AddrsFactory AddrsFactory @@ -76,10 +80,11 @@ type BasicHost struct { proc goprocess.Process - ctx context.Context - cancel func() mx sync.Mutex lastAddrs []ma.Multiaddr + emitters struct { + evtLocalProtocolsUpdated event.Emitter + } } var _ host.Host = (*BasicHost)(nil) @@ -87,7 +92,6 @@ var _ host.Host = (*BasicHost)(nil) // HostOpts holds options that can be passed to NewHost in order to // customize construction of the *BasicHost. type HostOpts struct { - // MultistreamMuxer is essential for the *BasicHost and will use a sensible default value if omitted. MultistreamMuxer *msmux.MultistreamMuxer @@ -96,10 +100,6 @@ type HostOpts struct { // If below 0, timeouts on streams will be deactivated. NegotiationTimeout time.Duration - // IdentifyService holds an implementation of the /ipfs/id/ protocol. - // If omitted, a new *identify.IDService will be used. - IdentifyService *identify.IDService - // AddrsFactory holds a function which can be used to override or filter the result of Addrs. // If omitted, there's no override or filtering, and the results of Addrs and AllAddrs are the same. AddrsFactory AddrsFactory @@ -117,26 +117,35 @@ type HostOpts struct { // EnablePing indicates whether to instantiate the ping service EnablePing bool + + // UserAgent sets the user-agent for the host. Defaults to ClientVersion. + UserAgent string } // NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given inet.Network. func NewHost(ctx context.Context, net network.Network, opts *HostOpts) (*BasicHost, error) { - bgctx, cancel := context.WithCancel(ctx) - h := &BasicHost{ network: net, mux: msmux.NewMultistreamMuxer(), negtimeout: DefaultNegotiationTimeout, AddrsFactory: DefaultAddrsFactory, maResolver: madns.DefaultResolver, - ctx: bgctx, - cancel: cancel, + eventbus: eventbus.NewBus(), + } + + var err error + if h.emitters.evtLocalProtocolsUpdated, err = h.eventbus.Emitter(&event.EvtLocalProtocolsUpdated{}); err != nil { + return nil, err } h.proc = goprocessctx.WithContextAndTeardown(ctx, func() error { if h.natmgr != nil { h.natmgr.Close() } + if h.cmgr != nil { + h.cmgr.Close() + } + _ = h.emitters.evtLocalProtocolsUpdated.Close() return h.Network().Close() }) @@ -144,12 +153,12 @@ func NewHost(ctx context.Context, net network.Network, opts *HostOpts) (*BasicHo h.mux = opts.MultistreamMuxer } - if opts.IdentifyService != nil { - h.ids = opts.IdentifyService - } else { - // we can't set this as a default above because it depends on the *BasicHost. - h.ids = identify.NewIDService(bgctx, h) - } + // we can't set this as a default above because it depends on the *BasicHost. + h.ids = identify.NewIDService( + goprocessctx.WithProcessClosing(ctx, h.proc), + h, + identify.UserAgent(opts.UserAgent), + ) if uint64(opts.NegotiationTimeout) != 0 { h.negtimeout = opts.NegotiationTimeout @@ -203,7 +212,7 @@ func New(net network.Network, opts ...interface{}) *BasicHost { hostopts.NATManager = NewNATManager } case AddrsFactory: - hostopts.AddrsFactory = AddrsFactory(o) + hostopts.AddrsFactory = o case connmgr.ConnManager: hostopts.ConnManager = o case *madns.Resolver: @@ -223,7 +232,7 @@ func New(net network.Network, opts ...interface{}) *BasicHost { // Start starts background tasks in the host func (h *BasicHost) Start() { - go h.background() + h.proc.Go(h.background) } // newConnHandler is the remote-opened conn handler for inet.Network @@ -248,7 +257,7 @@ func (h *BasicHost) newStreamHandler(s network.Stream) { } lzc, protoID, handle, err := h.Mux().NegotiateLazy(s) - took := time.Now().Sub(before) + took := time.Since(before) if err != nil { if err == io.EOF { logf := log.Debugf @@ -300,7 +309,7 @@ func (h *BasicHost) PushIdentify() { } } -func (h *BasicHost) background() { +func (h *BasicHost) background(p goprocess.Process) { // periodically schedules an IdentifyPush to update our peers for changes // in our address set (if needed) ticker := time.NewTicker(1 * time.Minute) @@ -318,7 +327,7 @@ func (h *BasicHost) background() { case <-ticker.C: h.PushIdentify() - case <-h.ctx.Done(): + case <-p.Closing(): return } } @@ -369,6 +378,10 @@ func (h *BasicHost) IDService() *identify.IDService { return h.ids } +func (h *BasicHost) EventBus() event.Bus { + return h.eventbus +} + // SetStreamHandler sets the protocol handler on the Host's Mux. // This is equivalent to: // host.Mux().SetHandler(proto, handler) @@ -380,6 +393,9 @@ func (h *BasicHost) SetStreamHandler(pid protocol.ID, handler network.StreamHand handler(is) return nil }) + h.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{ + Added: []protocol.ID{pid}, + }) } // SetStreamHandlerMatch sets the protocol handler on the Host's Mux @@ -391,11 +407,17 @@ func (h *BasicHost) SetStreamHandlerMatch(pid protocol.ID, m func(string) bool, handler(is) return nil }) + h.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{ + Added: []protocol.ID{pid}, + }) } // RemoveStreamHandler returns .. func (h *BasicHost) RemoveStreamHandler(pid protocol.ID) { h.Mux().RemoveHandler(string(pid)) + h.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{ + Removed: []protocol.ID{pid}, + }) } // NewStream opens a new stream to given peer p, and writes a p2p/protocol @@ -724,8 +746,13 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr { // Close shuts down the Host's services (network, etc). func (h *BasicHost) Close() error { - h.cancel() - h.cmgr.Close() + // You're thinking of adding some teardown logic here, right? Well + // don't! Add any process teardown logic to the teardown function in the + // constructor. + // + // This: + // 1. May be called multiple times. + // 2. May _never_ be called if the host is stopped by the context. return h.proc.Close() } diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/addrsplosion.go b/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/addrsplosion.go index 89965bca4..3b0e6355d 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/addrsplosion.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/addrsplosion.go @@ -5,7 +5,6 @@ import ( circuit "github.com/libp2p/go-libp2p-circuit" ma "github.com/multiformats/go-multiaddr" - dns "github.com/multiformats/go-multiaddr-dns" manet "github.com/multiformats/go-multiaddr-net" ) @@ -56,7 +55,7 @@ func isRelayAddr(a ma.Multiaddr) bool { func isDNSAddr(a ma.Multiaddr) bool { if first, _ := ma.SplitFirst(a); first != nil { switch first.Protocol().Code { - case dns.P_DNS4, dns.P_DNS6, dns.P_DNSADDR: + case ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR: return true } } diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/autorelay.go b/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/autorelay.go index ac381ac62..abab272e3 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/autorelay.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/host/relay/autorelay.go @@ -12,7 +12,7 @@ import ( "github.com/libp2p/go-libp2p-core/routing" autonat "github.com/libp2p/go-libp2p-autonat" - _ "github.com/libp2p/go-libp2p-circuit" + circuit "github.com/libp2p/go-libp2p-circuit" discovery "github.com/libp2p/go-libp2p-discovery" basic "github.com/libp2p/go-libp2p/p2p/host/basic" @@ -197,6 +197,17 @@ func (ar *AutoRelay) tryRelay(ctx context.Context, pi peer.AddrInfo) bool { return false } + ok, err := circuit.CanHop(ctx, ar.host, pi.ID) + if err != nil { + log.Debugf("error querying relay: %s", err.Error()) + return false + } + + if !ok { + // not a hop relay + return false + } + ar.mx.Lock() defer ar.mx.Unlock() diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/host/routed/routed.go b/vendor/github.com/libp2p/go-libp2p/p2p/host/routed/routed.go index 1282020bc..aecab0956 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/host/routed/routed.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/host/routed/routed.go @@ -6,6 +6,7 @@ import ( "time" "github.com/libp2p/go-libp2p-core/connmgr" + "github.com/libp2p/go-libp2p-core/event" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" @@ -153,6 +154,10 @@ func (rh *RoutedHost) Mux() protocol.Switch { return rh.host.Mux() } +func (rh *RoutedHost) EventBus() event.Bus { + return rh.host.EventBus() +} + func (rh *RoutedHost) SetStreamHandler(pid protocol.ID, handler network.StreamHandler) { rh.host.SetStreamHandler(pid, handler) } diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id.go b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id.go index a3ddddaa4..35e2e57ad 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id.go @@ -2,23 +2,26 @@ package identify import ( "context" + "fmt" + "runtime/debug" "sync" "time" + "github.com/libp2p/go-eventbus" ic "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/event" "github.com/libp2p/go-libp2p-core/helpers" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" + "github.com/libp2p/go-libp2p-core/protocol" pb "github.com/libp2p/go-libp2p/p2p/protocol/identify/pb" ggio "github.com/gogo/protobuf/io" logging "github.com/ipfs/go-log" - lgbl "github.com/libp2p/go-libp2p-loggables" - ma "github.com/multiformats/go-multiaddr" msmux "github.com/multiformats/go-multistream" ) @@ -28,14 +31,29 @@ var log = logging.Logger("net/identify") // ID is the protocol.ID of the Identify Service. const ID = "/ipfs/id/1.0.0" -// IDPush is the protocol.ID of the Identify push protocol -const IDPush = "/ipfs/id/push/1.0.0" - // LibP2PVersion holds the current protocol version for a client running this code // TODO(jbenet): fix the versioning mess. +// XXX: Don't change this till 2020. You'll break all go-ipfs versions prior to +// 0.4.17 which asserted an exact version match. const LibP2PVersion = "ipfs/0.1.0" -var ClientVersion = "go-libp2p/3.3.4" +// ClientVersion is the default user agent. +// +// Deprecated: Set this with the UserAgent option. +var ClientVersion = "github.com/libp2p/go-libp2p" + +func init() { + bi, ok := debug.ReadBuildInfo() + if !ok { + return + } + version := bi.Main.Version + if version == "(devel)" { + ClientVersion = bi.Main.Path + } else { + ClientVersion = fmt.Sprintf("%s@%s", bi.Main.Path, bi.Main.Version) + } +} // transientTTL is a short ttl for invalidated previously connected addrs const transientTTL = 10 * time.Second @@ -49,7 +67,8 @@ const transientTTL = 10 * time.Second // * Our IPFS Agent Version // * Our public Listen Addresses type IDService struct { - Host host.Host + Host host.Host + UserAgent string ctx context.Context @@ -63,23 +82,78 @@ type IDService struct { // our own observed addresses. // TODO: instead of expiring, remove these when we disconnect observedAddrs *ObservedAddrSet + + subscription event.Subscription + emitters struct { + evtPeerProtocolsUpdated event.Emitter + } } // NewIDService constructs a new *IDService and activates it by // attaching its stream handler to the given host.Host. -func NewIDService(ctx context.Context, h host.Host) *IDService { +func NewIDService(ctx context.Context, h host.Host, opts ...Option) *IDService { + var cfg config + for _, opt := range opts { + opt(&cfg) + } + + userAgent := ClientVersion + if cfg.userAgent != "" { + userAgent = cfg.userAgent + } + s := &IDService{ - Host: h, + Host: h, + UserAgent: userAgent, + ctx: ctx, currid: make(map[network.Conn]chan struct{}), observedAddrs: NewObservedAddrSet(ctx), } + + // handle local protocol handler updates, and push deltas to peers. + var err error + s.subscription, err = h.EventBus().Subscribe(&event.EvtLocalProtocolsUpdated{}, eventbus.BufSize(128)) + if err != nil { + log.Warningf("identify service not subscribed to local protocol handlers updates; err: %s", err) + } else { + go s.handleEvents() + } + + s.emitters.evtPeerProtocolsUpdated, err = h.EventBus().Emitter(&event.EvtPeerProtocolsUpdated{}) + if err != nil { + log.Warningf("identify service not emitting peer protocol updates; err: %s", err) + } + h.SetStreamHandler(ID, s.requestHandler) h.SetStreamHandler(IDPush, s.pushHandler) + h.SetStreamHandler(IDDelta, s.deltaHandler) h.Network().Notify((*netNotifiee)(s)) return s } +func (ids *IDService) handleEvents() { + sub := ids.subscription + defer func() { + _ = sub.Close() + // drain the channel. + for range sub.Out() { + } + }() + + for { + select { + case evt, more := <-sub.Out(): + if !more { + return + } + ids.fireProtocolDelta(evt.(event.EvtLocalProtocolsUpdated)) + case <-ids.ctx.Done(): + return + } + } +} + // OwnObservedAddrs returns the addresses peers have reported we've dialed from func (ids *IDService) OwnObservedAddrs() []ma.Multiaddr { return ids.observedAddrs.Addrs() @@ -137,8 +211,7 @@ func (ids *IDService) requestHandler(s network.Stream) { ids.populateMessage(&mes, s.Conn()) w.WriteMsg(&mes) - log.Debugf("%s sent message to %s %s", ID, - c.RemotePeer(), c.RemoteMultiaddr()) + log.Debugf("%s sent message to %s %s", ID, c.RemotePeer(), c.RemoteMultiaddr()) } func (ids *IDService) responseHandler(s network.Stream) { @@ -151,29 +224,51 @@ func (ids *IDService) responseHandler(s network.Stream) { s.Reset() return } + + defer func() { go helpers.FullClose(s) }() + + log.Debugf("%s received message from %s %s", s.Protocol(), c.RemotePeer(), c.RemoteMultiaddr()) ids.consumeMessage(&mes, c) - log.Debugf("%s received message from %s %s", ID, - c.RemotePeer(), c.RemoteMultiaddr()) - - go helpers.FullClose(s) } -func (ids *IDService) pushHandler(s network.Stream) { - ids.responseHandler(s) -} - -func (ids *IDService) Push() { +func (ids *IDService) broadcast(proto protocol.ID, payloadWriter func(s network.Stream)) { var wg sync.WaitGroup ctx, cancel := context.WithTimeout(ids.ctx, 30*time.Second) - ctx = network.WithNoDial(ctx, "identify push") + ctx = network.WithNoDial(ctx, string(proto)) + pstore := ids.Host.Peerstore() for _, p := range ids.Host.Network().Peers() { wg.Add(1) - go func(p peer.ID) { + + go func(p peer.ID, conns []network.Conn) { defer wg.Done() - s, err := ids.Host.NewStream(ctx, p, IDPush) + // if we're in the process of identifying the connection, let's wait. + // we don't use ids.IdentifyWait() to avoid unnecessary channel creation. + Loop: + for _, c := range conns { + ids.currmu.RLock() + if wait, ok := ids.currid[c]; ok { + ids.currmu.RUnlock() + select { + case <-wait: + break Loop + case <-ctx.Done(): + return + } + } + ids.currmu.RUnlock() + } + + // avoid the unnecessary stream if the peer does not support the protocol. + if sup, err := pstore.SupportsProtocols(p, string(proto)); err != nil && len(sup) == 0 { + // the peer does not support the required protocol. + return + } + // if the peerstore query errors, we go ahead anyway. + + s, err := ids.Host.NewStream(ctx, p, proto) if err != nil { log.Debugf("error opening push stream to %s: %s", p, err.Error()) return @@ -181,7 +276,7 @@ func (ids *IDService) Push() { rch := make(chan struct{}, 1) go func() { - ids.requestHandler(s) + payloadWriter(s) rch <- struct{}{} }() @@ -191,7 +286,7 @@ func (ids *IDService) Push() { // this is taking too long, abort! s.Reset() } - }(p) + }(p, ids.Host.Network().ConnsToPeer(p)) } // this supervisory goroutine is necessary to cancel the context @@ -202,12 +297,11 @@ func (ids *IDService) Push() { } func (ids *IDService) populateMessage(mes *pb.Identify, c network.Conn) { - // set protocols this node is currently handling protos := ids.Host.Mux().Protocols() mes.Protocols = make([]string, len(protos)) for i, p := range protos { - mes.Protocols[i] = string(p) + mes.Protocols[i] = p } // observed address so other side is informed of their @@ -245,7 +339,7 @@ func (ids *IDService) populateMessage(mes *pb.Identify, c network.Conn) { // set protocol versions pv := LibP2PVersion - av := ClientVersion + av := ids.UserAgent mes.ProtocolVersion = &pv mes.AgentVersion = &av } @@ -414,7 +508,7 @@ func HasConsistentTransport(a ma.Multiaddr, green []ma.Multiaddr) bool { // IdentifyWait returns a channel which will be closed once // "ProtocolIdentify" (handshake3) finishes on given conn. // This happens async so the connection can start to be used -// even if handshake3 knowledge is not necesary. +// even if handshake3 knowledge is not necessary. // Users **MUST** call IdentifyWait _after_ IdentifyConn func (ids *IDService) IdentifyWait(c network.Conn) <-chan struct{} { ids.currmu.Lock() @@ -507,13 +601,3 @@ func (nn *netNotifiee) OpenedStream(n network.Network, v network.Stream) {} func (nn *netNotifiee) ClosedStream(n network.Network, v network.Stream) {} func (nn *netNotifiee) Listen(n network.Network, a ma.Multiaddr) {} func (nn *netNotifiee) ListenClose(n network.Network, a ma.Multiaddr) {} - -func logProtocolMismatchDisconnect(c network.Conn, protocol, agent string) { - lm := make(lgbl.DeferredMap) - lm["remotePeer"] = func() interface{} { return c.RemotePeer().Pretty() } - lm["remoteAddr"] = func() interface{} { return c.RemoteMultiaddr().String() } - lm["protocolVersion"] = protocol - lm["agentVersion"] = agent - log.Event(context.TODO(), "IdentifyProtocolMismatch", lm) - log.Debugf("IdentifyProtocolMismatch %s %s %s (disconnected)", c.RemotePeer(), protocol, agent) -} diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_delta.go b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_delta.go new file mode 100644 index 000000000..2cc95b729 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_delta.go @@ -0,0 +1,83 @@ +package identify + +import ( + "github.com/libp2p/go-libp2p-core/event" + "github.com/libp2p/go-libp2p-core/helpers" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" + + ggio "github.com/gogo/protobuf/io" + pb "github.com/libp2p/go-libp2p/p2p/protocol/identify/pb" +) + +const IDDelta = "/p2p/id/delta/1.0.0" + +// deltaHandler handles incoming delta updates from peers. +func (ids *IDService) deltaHandler(s network.Stream) { + c := s.Conn() + + r := ggio.NewDelimitedReader(s, 2048) + mes := pb.Identify{} + if err := r.ReadMsg(&mes); err != nil { + log.Warning("error reading identify message: ", err) + s.Reset() + return + } + + defer func() { go helpers.FullClose(s) }() + log.Debugf("%s received message from %s %s", s.Protocol(), c.RemotePeer(), c.RemoteMultiaddr()) + + delta := mes.GetDelta() + if delta == nil { + return + } + + p := s.Conn().RemotePeer() + if err := ids.consumeDelta(p, delta); err != nil { + log.Warningf("delta update from peer %s failed: %s", p, err) + } +} + +// fireProtocolDelta fires a delta message to all connected peers to signal a local protocol table update. +func (ids *IDService) fireProtocolDelta(evt event.EvtLocalProtocolsUpdated) { + mes := pb.Identify{ + Delta: &pb.Delta{ + AddedProtocols: protocol.ConvertToStrings(evt.Added), + RmProtocols: protocol.ConvertToStrings(evt.Removed), + }, + } + deltaWriter := func(s network.Stream) { + defer helpers.FullClose(s) + c := s.Conn() + err := ggio.NewDelimitedWriter(s).WriteMsg(&mes) + if err != nil { + log.Warningf("%s error while sending delta update to %s: %s", IDDelta, c.RemotePeer(), c.RemoteMultiaddr()) + return + } + log.Debugf("%s sent delta update to %s: %s", IDDelta, c.RemotePeer(), c.RemoteMultiaddr()) + } + ids.broadcast(IDDelta, deltaWriter) +} + +// consumeDelta processes an incoming delta from a peer, updating the peerstore +// and emitting the appropriate events. +func (ids *IDService) consumeDelta(id peer.ID, delta *pb.Delta) error { + err := ids.Host.Peerstore().AddProtocols(id, delta.GetAddedProtocols()...) + if err != nil { + return err + } + + err = ids.Host.Peerstore().RemoveProtocols(id, delta.GetRmProtocols()...) + if err != nil { + return err + } + + evt := event.EvtPeerProtocolsUpdated{ + Peer: id, + Added: protocol.ConvertFromStrings(delta.GetAddedProtocols()), + Removed: protocol.ConvertFromStrings(delta.GetRmProtocols()), + } + ids.emitters.evtPeerProtocolsUpdated.Emit(evt) + return nil +} diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_push.go b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_push.go new file mode 100644 index 000000000..7f0104ce7 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/id_push.go @@ -0,0 +1,20 @@ +package identify + +import "github.com/libp2p/go-libp2p-core/network" + +// IDPush is the protocol.ID of the Identify push protocol. It sends full identify messages containing +// the current state of the peer. +// +// It is in the process of being replaced by identify delta, which sends only diffs for better +// resource utilisation. +const IDPush = "/ipfs/id/push/1.0.0" + +// Push pushes a full identify message to all peers containing the current state. +func (ids *IDService) Push() { + ids.broadcast(IDPush, ids.requestHandler) +} + +// pushHandler handles incoming identify push streams. The behaviour is identical to the ordinary identify protocol. +func (ids *IDService) pushHandler(s network.Stream) { + ids.responseHandler(s) +} diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/opts.go b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/opts.go new file mode 100644 index 000000000..670b213b7 --- /dev/null +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/opts.go @@ -0,0 +1,15 @@ +package identify + +type config struct { + userAgent string +} + +// Option is an option function for identify. +type Option func(*config) + +// UserAgent sets the user agent this node will identify itself with to peers. +func UserAgent(ua string) Option { + return func(cfg *config) { + cfg.userAgent = ua + } +} diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.pb.go b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.pb.go index de1275ba3..8480e5ba5 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.pb.go +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.pb.go @@ -21,6 +21,63 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +type Delta struct { + // new protocols now serviced by the peer. + AddedProtocols []string `protobuf:"bytes,1,rep,name=added_protocols,json=addedProtocols" json:"added_protocols,omitempty"` + // protocols dropped by the peer. + RmProtocols []string `protobuf:"bytes,2,rep,name=rm_protocols,json=rmProtocols" json:"rm_protocols,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Delta) Reset() { *m = Delta{} } +func (m *Delta) String() string { return proto.CompactTextString(m) } +func (*Delta) ProtoMessage() {} +func (*Delta) Descriptor() ([]byte, []int) { + return fileDescriptor_83f1e7e6b485409f, []int{0} +} +func (m *Delta) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Delta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Delta.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Delta) XXX_Merge(src proto.Message) { + xxx_messageInfo_Delta.Merge(m, src) +} +func (m *Delta) XXX_Size() int { + return m.Size() +} +func (m *Delta) XXX_DiscardUnknown() { + xxx_messageInfo_Delta.DiscardUnknown(m) +} + +var xxx_messageInfo_Delta proto.InternalMessageInfo + +func (m *Delta) GetAddedProtocols() []string { + if m != nil { + return m.AddedProtocols + } + return nil +} + +func (m *Delta) GetRmProtocols() []string { + if m != nil { + return m.RmProtocols + } + return nil +} + type Identify struct { // protocolVersion determines compatibility between peers ProtocolVersion *string `protobuf:"bytes,5,opt,name=protocolVersion" json:"protocolVersion,omitempty"` @@ -38,7 +95,9 @@ type Identify struct { // determine whether its connection to the local peer goes through NAT. ObservedAddr []byte `protobuf:"bytes,4,opt,name=observedAddr" json:"observedAddr,omitempty"` // protocols are the services this node is running - Protocols []string `protobuf:"bytes,3,rep,name=protocols" json:"protocols,omitempty"` + Protocols []string `protobuf:"bytes,3,rep,name=protocols" json:"protocols,omitempty"` + // a delta update is incompatible with everything else. If this field is included, none of the others can appear. + Delta *Delta `protobuf:"bytes,7,opt,name=delta" json:"delta,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -48,7 +107,7 @@ func (m *Identify) Reset() { *m = Identify{} } func (m *Identify) String() string { return proto.CompactTextString(m) } func (*Identify) ProtoMessage() {} func (*Identify) Descriptor() ([]byte, []int) { - return fileDescriptor_83f1e7e6b485409f, []int{0} + return fileDescriptor_83f1e7e6b485409f, []int{1} } func (m *Identify) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -119,26 +178,89 @@ func (m *Identify) GetProtocols() []string { return nil } +func (m *Identify) GetDelta() *Delta { + if m != nil { + return m.Delta + } + return nil +} + func init() { + proto.RegisterType((*Delta)(nil), "identify.pb.Delta") proto.RegisterType((*Identify)(nil), "identify.pb.Identify") } func init() { proto.RegisterFile("identify.proto", fileDescriptor_83f1e7e6b485409f) } var fileDescriptor_83f1e7e6b485409f = []byte{ - // 187 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0x4c, 0x49, 0xcd, - 0x2b, 0xc9, 0x4c, 0xab, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x46, 0xf0, 0x93, 0x94, - 0x6e, 0x31, 0x72, 0x71, 0x78, 0x42, 0xf9, 0x42, 0x1a, 0x5c, 0xfc, 0x60, 0x25, 0xc9, 0xf9, 0x39, - 0x61, 0xa9, 0x45, 0xc5, 0x99, 0xf9, 0x79, 0x12, 0xac, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0xe8, 0xc2, - 0x42, 0x4a, 0x5c, 0x3c, 0x89, 0xe9, 0xa9, 0x79, 0x25, 0x30, 0x65, 0x6c, 0x60, 0x65, 0x28, 0x62, - 0x42, 0x32, 0x5c, 0x9c, 0x05, 0xa5, 0x49, 0x39, 0x99, 0xc9, 0xde, 0xa9, 0x95, 0x12, 0x8c, 0x0a, - 0x8c, 0x1a, 0x3c, 0x41, 0x08, 0x01, 0x21, 0x05, 0x2e, 0xee, 0x9c, 0xcc, 0xe2, 0x92, 0xd4, 0x3c, - 0xc7, 0x94, 0x94, 0xa2, 0x62, 0x09, 0x26, 0x05, 0x66, 0x0d, 0x9e, 0x20, 0x64, 0x21, 0x90, 0x1d, - 0xf9, 0x49, 0xc5, 0xa9, 0x45, 0x65, 0xa9, 0x29, 0x20, 0x01, 0x09, 0x16, 0xb0, 0x11, 0x28, 0x62, - 0x60, 0x3b, 0xa0, 0x4e, 0x2b, 0x96, 0x60, 0x56, 0x60, 0xd6, 0xe0, 0x0c, 0x42, 0x08, 0x38, 0xf1, - 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x80, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xc2, 0x2c, 0x19, 0x46, 0x08, 0x01, 0x00, 0x00, + // 251 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xb1, 0x4e, 0xc3, 0x30, + 0x14, 0x45, 0xe5, 0x96, 0x02, 0x79, 0xb1, 0x5a, 0xe9, 0x4d, 0x1e, 0x50, 0x64, 0xb2, 0xe0, 0x29, + 0x03, 0x7f, 0x00, 0x62, 0x41, 0x2c, 0xc8, 0x48, 0xac, 0x28, 0xa9, 0x1f, 0xc8, 0x52, 0x1a, 0x57, + 0x8e, 0x41, 0xea, 0xce, 0xc7, 0x31, 0xf2, 0x09, 0x28, 0x5f, 0x82, 0xe2, 0x92, 0x26, 0x65, 0xf4, + 0xd1, 0x91, 0xef, 0xbb, 0x17, 0x96, 0xd6, 0x50, 0x13, 0xec, 0xeb, 0xae, 0xd8, 0x7a, 0x17, 0x1c, + 0xa6, 0xe3, 0xbb, 0xca, 0x9f, 0x60, 0x71, 0x47, 0x75, 0x28, 0xf1, 0x0a, 0x56, 0xa5, 0x31, 0x64, + 0x5e, 0xa2, 0xb4, 0x76, 0x75, 0x2b, 0x98, 0x9c, 0xab, 0x44, 0x2f, 0x23, 0x7e, 0x1c, 0x28, 0x5e, + 0x02, 0xf7, 0x9b, 0x89, 0x35, 0x8b, 0x56, 0xea, 0x37, 0x07, 0x25, 0xff, 0x9c, 0xc1, 0xf9, 0xfd, + 0x5f, 0x08, 0x2a, 0x58, 0x0d, 0xf2, 0x33, 0xf9, 0xd6, 0xba, 0x46, 0x2c, 0x24, 0x53, 0x89, 0xfe, + 0x8f, 0x31, 0x07, 0x5e, 0xbe, 0x51, 0x13, 0x06, 0xed, 0x34, 0x6a, 0x47, 0x0c, 0x2f, 0x20, 0xd9, + 0xbe, 0x57, 0xb5, 0x5d, 0x3f, 0xd0, 0x4e, 0x30, 0xc9, 0x14, 0xd7, 0x23, 0x40, 0x09, 0x69, 0x6d, + 0xdb, 0x40, 0xcd, 0x8d, 0x31, 0x7e, 0x7f, 0x1a, 0xd7, 0x53, 0xd4, 0x67, 0xb8, 0xaa, 0x25, 0xff, + 0x41, 0xa6, 0x07, 0xe2, 0x24, 0x7e, 0x71, 0xc4, 0x62, 0xc6, 0xa1, 0xde, 0x3c, 0xd6, 0x1b, 0x01, + 0x2a, 0x58, 0x98, 0x7e, 0x31, 0x71, 0x26, 0x99, 0x4a, 0xaf, 0xb1, 0x98, 0xcc, 0x59, 0xc4, 0x2d, + 0xf5, 0x5e, 0xb8, 0xe5, 0x5f, 0x5d, 0xc6, 0xbe, 0xbb, 0x8c, 0xfd, 0x74, 0x19, 0xfb, 0x0d, 0x00, + 0x00, 0xff, 0xff, 0xa1, 0x77, 0x03, 0x42, 0x87, 0x01, 0x00, 0x00, +} + +func (m *Delta) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Delta) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.AddedProtocols) > 0 { + for _, s := range m.AddedProtocols { + dAtA[i] = 0xa + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.RmProtocols) > 0 { + for _, s := range m.RmProtocols { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil } func (m *Identify) Marshal() (dAtA []byte, err error) { @@ -203,6 +325,16 @@ func (m *Identify) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintIdentify(dAtA, i, uint64(len(*m.AgentVersion))) i += copy(dAtA[i:], *m.AgentVersion) } + if m.Delta != nil { + dAtA[i] = 0x3a + i++ + i = encodeVarintIdentify(dAtA, i, uint64(m.Delta.Size())) + n1, err := m.Delta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -218,6 +350,30 @@ func encodeVarintIdentify(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return offset + 1 } +func (m *Delta) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AddedProtocols) > 0 { + for _, s := range m.AddedProtocols { + l = len(s) + n += 1 + l + sovIdentify(uint64(l)) + } + } + if len(m.RmProtocols) > 0 { + for _, s := range m.RmProtocols { + l = len(s) + n += 1 + l + sovIdentify(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *Identify) Size() (n int) { if m == nil { return 0 @@ -252,6 +408,10 @@ func (m *Identify) Size() (n int) { l = len(*m.AgentVersion) n += 1 + l + sovIdentify(uint64(l)) } + if m.Delta != nil { + l = m.Delta.Size() + n += 1 + l + sovIdentify(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -271,6 +431,124 @@ func sovIdentify(x uint64) (n int) { func sozIdentify(x uint64) (n int) { return sovIdentify(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *Delta) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIdentify + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Delta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Delta: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AddedProtocols", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIdentify + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthIdentify + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIdentify + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AddedProtocols = append(m.AddedProtocols, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RmProtocols", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIdentify + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthIdentify + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIdentify + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RmProtocols = append(m.RmProtocols, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipIdentify(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthIdentify + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthIdentify + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Identify) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -498,6 +776,42 @@ func (m *Identify) Unmarshal(dAtA []byte) error { s := string(dAtA[iNdEx:postIndex]) m.AgentVersion = &s iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Delta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIdentify + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthIdentify + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthIdentify + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Delta == nil { + m.Delta = &Delta{} + } + if err := m.Delta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipIdentify(dAtA[iNdEx:]) diff --git a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.proto b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.proto index 5270c4cf5..44283870f 100644 --- a/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.proto +++ b/vendor/github.com/libp2p/go-libp2p/p2p/protocol/identify/pb/identify.proto @@ -2,6 +2,13 @@ syntax = "proto2"; package identify.pb; +message Delta { + // new protocols now serviced by the peer. + repeated string added_protocols = 1; + // protocols dropped by the peer. + repeated string rm_protocols = 2; +} + message Identify { // protocolVersion determines compatibility between peers @@ -26,4 +33,7 @@ message Identify { // protocols are the services this node is running repeated string protocols = 3; + + // a delta update is incompatible with everything else. If this field is included, none of the others can appear. + optional Delta delta = 7; } diff --git a/vendor/github.com/libp2p/go-libp2p/package-list.json b/vendor/github.com/libp2p/go-libp2p/package-list.json index e29a74103..21971bba1 100644 --- a/vendor/github.com/libp2p/go-libp2p/package-list.json +++ b/vendor/github.com/libp2p/go-libp2p/package-list.json @@ -8,15 +8,13 @@ "rows": [ "Libp2p", ["libp2p/go-libp2p", "go-libp2p", "go-libp2p entry point"], - ["libp2p/go-libp2p-host", "go-libp2p-host", "libp2p \"host\" interface"], + ["libp2p/go-libp2p-core", "go-libp2p-core", "core interfaces, types, and abstractions"], ["libp2p/go-libp2p-blankhost", "go-libp2p-blankhost", "minimal implementation of the \"host\" interface"], "Network", - ["libp2p/go-libp2p-net", "go-libp2p-net", "libp2p connection and \"network\" interfaces"], - ["libp2p/go-libp2p-swarm", "go-libp2p-swarm", "reference implementation"], + ["libp2p/go-libp2p-swarm", "go-libp2p-swarm", "reference implementation of network state machine"], "Transport", - ["libp2p/go-libp2p-transport", "go-libp2p-transport", "interfaces"], ["libp2p/go-ws-transport", "go-ws-transport", "WebSocket transport"], ["libp2p/go-tcp-transport", "go-tcp-transport", "TCP transport"], ["libp2p/go-libp2p-quic-transport", "go-libp2p-quic-transport", "QUIC transport"], @@ -27,34 +25,31 @@ ["libp2p/go-libp2p-reuseport-transport", "go-libp2p-reuseport-transport", "partial transport for building transports that reuse ports"], "Encrypted Channels", - ["libp2p/go-conn-security", "go-conn-security", "interfaces"], ["libp2p/go-libp2p-secio", "go-libp2p-secio", "SecIO crypto channel"], + ["libp2p/go-libp2p-tls-transport", "go-libp2p-tls-transport", "TLS 1.3+ crypto channel"], ["libp2p/go-conn-security-multistream", "go-conn-security-multistream", "multistream multiplexed meta crypto channel"], "Private Network", - ["libp2p/go-libp2p-interface-pnet", "go-libp2p-interface-pnet", "interfaces"], - ["libp2p/go-libp2p-pnet", "go-libp2p-pnet", "reference implementation"], + ["libp2p/go-libp2p-pnet", "go-libp2p-pnet", "reference private networking implementation"], "Stream Muxers", - ["libp2p/go-stream-muxer", "go-stream-muxer", "interfaces"], - ["whyrusleeping/go-smux-yamux", "go-smux-yamux", "YAMUX stream multiplexer"], - ["whyrusleeping/go-smux-mplex", "go-smux-mplex", "MPLEX stream multiplexer"], + ["libp2p/go-libp2p-yamux", "go-libp2p-yamux", "YAMUX stream multiplexer"], + ["libp2p/go-libp2p-mplex", "go-libp2p-mplex", "MPLEX stream multiplexer"], "NAT Traversal", ["libp2p/go-libp2p-nat", "go-libp2p-nat"], "Peerstore", - ["libp2p/go-libp2p-peerstore", "go-libp2p-peerstore", "interfaces and reference implementation"], + ["libp2p/go-libp2p-peerstore", "go-libp2p-peerstore", "reference implementation of peer metadata storage component"], "Connection Manager", - ["libp2p/go-libp2p-interface-connmgr", "go-libp2p-interface-connmgr", "interface"], - ["libp2p/go-libp2p-connmgr", "go-libp2p-connmgr", "reference implementation"], + ["libp2p/go-libp2p-connmgr", "go-libp2p-connmgr", "reference implementation of connection manager"], "Routing", - ["libp2p/go-libp2p-routing", "go-libp2p-routing", "routing interfaces"], ["libp2p/go-libp2p-record", "go-libp2p-record", "record type and validator logic"], - ["libp2p/go-libp2p-routing-helpers", "go-libp2p-routing-helpers", "helpers for composing routers"], ["libp2p/go-libp2p-kad-dht", "go-libp2p-kad-dht", "Kademlia-like router"], + ["libp2p/go-libp2p-kbucket", "go-libp2p-kbucket", "Kademlia routing table helper types"], + ["libp2p/go-libp2p-coral-dht", "go-libp2p-coral-dht", "Router based on Coral DHT"], ["libp2p/go-libp2p-pubsub-router", "go-libp2p-pubsub-router", "record-store over pubsub adapter"], "Consensus", @@ -67,15 +62,6 @@ "RPC", ["libp2p/go-libp2p-gorpc", "go-libp2p-gorpc", "a simple RPC library for libp2p"], - "Metrics", - ["libp2p/go-libp2p-metrics", "go-libp2p-metrics", "libp2p metrics interfaces/collectors"], - - "Data Types", - ["libp2p/go-libp2p-peer", "go-libp2p-peer", "libp2p peer-ID datatype"], - ["libp2p/go-libp2p-crypto", "go-libp2p-crypto", "libp2p key types"], - ["libp2p/go-libp2p-protocol", "go-libp2p-protocol", "libp2p protocol datatype"], - ["libp2p/go-libp2p-kbucket", "go-libp2p-kbucket", "Kademlia routing table helper types"], - "Utilities/miscellaneous", ["libp2p/go-libp2p-loggables", "go-libp2p-loggables", "logging helpers"], ["libp2p/go-maddr-filter", "go-maddr-filter", "multiaddr filtering helpers"], @@ -87,11 +73,33 @@ ["libp2p/go-reuseport", "go-reuseport", "enables reuse of addresses"], ["libp2p/go-sockaddr", "go-sockaddr", "utils for sockaddr conversions"], ["libp2p/go-flow-metrics", "go-flow-metrics", "metrics library"], + ["libp2p/go-libp2p-gostream", "go-libp2p-gostream", "Go 'net' wrappers for libp2p"], + ["libp2p/go-libp2p-http", "go-libp2p-http", "HTTP on top of libp2p streams"], "Testing and examples", - ["libp2p/go-testutil", "go-testutil", "a collection of testing utilities for ipfs and libp2p"], + ["libp2p/go-libp2p-testing", "go-libp2p-testing", "a collection of testing utilities for libp2p"], ["libp2p/go-libp2p-examples", "go-libp2p-examples", "go-libp2p examples and tutorials"], - ["libp2p/go-libp2p-circuit-progs", "go-libp2p-circuit-progs", "testing programs for go-libp2p-circuit"] + "Deprecated", + ["libp2p/go-conn-security", "go-conn-security", "absorbed into go-libp2p-core"], + ["libp2p/go-peerstream", "go-peerstream", "early work that informed libp2p design"], + ["libp2p/go-stream-muxer", "go-stream-muxer", "absorbed into go-libp2p-core"], + ["libp2p/go-testutil", "go-testutil", "replaced by go-libp2p-testing"], + ["libp2p/go-libp2p-circuit-progs", "go-libp2p-circuit-progs", "testing programs for go-libp2p-circuit"], + ["libp2p/go-libp2p-crypto", "go-libp2p-crypto", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-conn", "go-libp2p-conn", "replaced by go-libp2p-swarm and go-libp2p-transport-upgrader"], + ["libp2p/go-libp2p-discovery", "go-libp2p-discovery", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-dummy-conn", "go-libp2p-dummy-conn", "implempentation of deprecated interface"], + ["libp2p/go-libp2p-host", "go-libp2p-host", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-identify", "go-libp2p-identify", "moved to go-libp2p"], + ["libp2p/go-libp2p-interface-conn", "go-libp2p-interface-conn", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-interface-connmgr", "go-libp2p-interface-connmgr", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-interface-pnet", "go-libp2p-interface-pnet", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-metrics", "go-libp2p-metrics", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-net", "go-libp2p-net", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-peer", "go-libp2p-peer", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-ping", "go-libp2p-ping", "moved to go-libp2p"], + ["libp2p/go-libp2p-protocol", "go-libp2p-protocol", "absorbed into go-libp2p-core"], + ["libp2p/go-libp2p-transport", "go-libp2p-transport", "absorbed into go-libp2p-core"] ] } diff --git a/vendor/github.com/libp2p/go-maddr-filter/filter.go b/vendor/github.com/libp2p/go-maddr-filter/filter.go index a555df518..4eb0c56b4 100644 --- a/vendor/github.com/libp2p/go-maddr-filter/filter.go +++ b/vendor/github.com/libp2p/go-maddr-filter/filter.go @@ -5,7 +5,6 @@ import ( "sync" ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr-net" ) // Action is an enum modelling all possible filter actions. @@ -112,17 +111,25 @@ func (fs *Filters) RemoveLiteral(ipnet net.IPNet) (removed bool) { // Instead, the highest-specific last filter should win; that way more specific filters // override more general ones. func (fs *Filters) AddrBlocked(a ma.Multiaddr) (deny bool) { - maddr := ma.Split(a) - if len(maddr) == 0 { - return fs.DefaultAction == ActionDeny - } - netaddr, err := manet.ToNetAddr(maddr[0]) - if err != nil { - // if we can't parse it, it's probably not blocked. - return fs.DefaultAction == ActionDeny - } - netip := net.ParseIP(netaddr.String()) - if netip == nil { + var ( + netip net.IP + found bool + ) + + ma.ForEach(a, func(c ma.Component) bool { + switch c.Protocol().Code { + case ma.P_IP6ZONE: + return true + case ma.P_IP6, ma.P_IP4: + found = true + netip = net.IP(c.RawValue()) + return false + default: + return false + } + }) + + if !found { return fs.DefaultAction == ActionDeny } diff --git a/vendor/github.com/libp2p/go-maddr-filter/go.mod b/vendor/github.com/libp2p/go-maddr-filter/go.mod index 4adb057dd..4e46b6552 100644 --- a/vendor/github.com/libp2p/go-maddr-filter/go.mod +++ b/vendor/github.com/libp2p/go-maddr-filter/go.mod @@ -1,6 +1,3 @@ module github.com/libp2p/go-maddr-filter -require ( - github.com/multiformats/go-multiaddr v0.0.1 - github.com/multiformats/go-multiaddr-net v0.0.1 -) +require github.com/multiformats/go-multiaddr v0.0.1 diff --git a/vendor/github.com/libp2p/go-maddr-filter/go.sum b/vendor/github.com/libp2p/go-maddr-filter/go.sum index 11cfae502..cbf49eb4e 100644 --- a/vendor/github.com/libp2p/go-maddr-filter/go.sum +++ b/vendor/github.com/libp2p/go-maddr-filter/go.sum @@ -10,10 +10,6 @@ github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr-dns v0.0.1 h1:jQt9c6tDSdQLIlBo4tXYx7QUHCPjxsB1zXcag/2S7zc= -github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= -github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= diff --git a/vendor/github.com/libp2p/go-msgio/chan.go b/vendor/github.com/libp2p/go-msgio/chan.go index 4e5183f5c..571393c1b 100644 --- a/vendor/github.com/libp2p/go-msgio/chan.go +++ b/vendor/github.com/libp2p/go-msgio/chan.go @@ -38,9 +38,6 @@ func (s *Chan) ReadFromWithPool(r io.Reader, p *pool.BufferPool) { // ReadFrom wraps the given io.Reader with a msgio.Reader, reads all // messages, ands sends them down the channel. func (s *Chan) readFrom(mr Reader) { - // single reader, no need for Mutex - mr.(*reader).lock = new(nullLocker) - Loop: for { buf, err := mr.ReadMsg() @@ -74,8 +71,6 @@ func (s *Chan) WriteTo(w io.Writer) { // if bottleneck, cycle around a set of buffers mw := NewWriter(w) - // single writer, no need for Mutex - mw.(*writer).lock = new(nullLocker) Loop: for { select { diff --git a/vendor/github.com/libp2p/go-msgio/msgio.go b/vendor/github.com/libp2p/go-msgio/msgio.go index 2a67025dc..5e61142c5 100644 --- a/vendor/github.com/libp2p/go-msgio/msgio.go +++ b/vendor/github.com/libp2p/go-msgio/msgio.go @@ -76,13 +76,20 @@ type ReadWriteCloser interface { type writer struct { W io.Writer - lock sync.Locker + pool *pool.BufferPool + lock sync.Mutex } // NewWriter wraps an io.Writer with a msgio framed writer. The msgio.Writer // will write the length prefix of every message written. func NewWriter(w io.Writer) WriteCloser { - return &writer{W: w, lock: new(sync.Mutex)} + return NewWriterWithPool(w, pool.GlobalPool) +} + +// NewWriterWithPool is identical to NewWriter but allows the user to pass a +// custom buffer pool. +func NewWriterWithPool(w io.Writer, p *pool.BufferPool) WriteCloser { + return &writer{W: w, pool: p} } func (s *writer) Write(msg []byte) (int, error) { @@ -96,10 +103,13 @@ func (s *writer) Write(msg []byte) (int, error) { func (s *writer) WriteMsg(msg []byte) (err error) { s.lock.Lock() defer s.lock.Unlock() - if err := WriteLen(s.W, len(msg)); err != nil { - return err - } - _, err = s.W.Write(msg) + + buf := s.pool.Get(len(msg) + lengthSize) + NBO.PutUint32(buf, uint32(len(msg))) + copy(buf[lengthSize:], msg) + _, err = s.W.Write(buf) + s.pool.Put(buf) + return err } @@ -114,10 +124,10 @@ func (s *writer) Close() error { type reader struct { R io.Reader - lbuf []byte + lbuf [lengthSize]byte next int pool *pool.BufferPool - lock sync.Locker + lock sync.Mutex max int // the maximal message size (in bytes) this reader handles } @@ -128,20 +138,29 @@ func NewReader(r io.Reader) ReadCloser { return NewReaderWithPool(r, pool.GlobalPool) } -// NewReaderWithPool wraps an io.Reader with a msgio framed reader. The msgio.Reader -// will read whole messages at a time (using the length). Assumes an equivalent -// writer on the other side. It uses a given pool.BufferPool +// NewReaderSize is equivalent to NewReader but allows one to +// specify a max message size. +func NewReaderSize(r io.Reader, maxMessageSize int) ReadCloser { + return NewReaderSizeWithPool(r, maxMessageSize, pool.GlobalPool) +} + +// NewReaderWithPool is the same as NewReader but allows one to specify a buffer +// pool. func NewReaderWithPool(r io.Reader, p *pool.BufferPool) ReadCloser { + return NewReaderSizeWithPool(r, defaultMaxSize, p) +} + +// NewReaderWithPool is the same as NewReader but allows one to specify a buffer +// pool and a max message size. +func NewReaderSizeWithPool(r io.Reader, maxMessageSize int, p *pool.BufferPool) ReadCloser { if p == nil { panic("nil pool") } return &reader{ R: r, - lbuf: make([]byte, lengthSize), next: -1, pool: p, - lock: new(sync.Mutex), - max: defaultMaxSize, + max: maxMessageSize, } } @@ -156,7 +175,7 @@ func (s *reader) NextMsgLen() (int, error) { func (s *reader) nextMsgLen() (int, error) { if s.next == -1 { - n, err := ReadLen(s.R, s.lbuf) + n, err := ReadLen(s.R, s.lbuf[:]) if err != nil { return 0, err } diff --git a/vendor/github.com/libp2p/go-msgio/varint.go b/vendor/github.com/libp2p/go-msgio/varint.go index 5915af916..0872fc36a 100644 --- a/vendor/github.com/libp2p/go-msgio/varint.go +++ b/vendor/github.com/libp2p/go-msgio/varint.go @@ -12,18 +12,21 @@ import ( type varintWriter struct { W io.Writer - lbuf []byte // for encoding varints - lock sync.Locker // for threadsafe writes + pool *pool.BufferPool + lock sync.Mutex // for threadsafe writes } // NewVarintWriter wraps an io.Writer with a varint msgio framed writer. // The msgio.Writer will write the length prefix of every message written // as a varint, using https://golang.org/pkg/encoding/binary/#PutUvarint func NewVarintWriter(w io.Writer) WriteCloser { + return NewVarintWriterWithPool(w, pool.GlobalPool) +} + +func NewVarintWriterWithPool(w io.Writer, p *pool.BufferPool) WriteCloser { return &varintWriter{ + pool: p, W: w, - lbuf: make([]byte, binary.MaxVarintLen64), - lock: new(sync.Mutex), } } @@ -39,12 +42,12 @@ func (s *varintWriter) WriteMsg(msg []byte) error { s.lock.Lock() defer s.lock.Unlock() - length := uint64(len(msg)) - n := binary.PutUvarint(s.lbuf, length) - if _, err := s.W.Write(s.lbuf[:n]); err != nil { - return err - } - _, err := s.W.Write(msg) + buf := s.pool.Get(len(msg) + binary.MaxVarintLen64) + n := binary.PutUvarint(buf, uint64(len(msg))) + n += copy(buf[n:], msg) + _, err := s.W.Write(buf[:n]) + s.pool.Put(buf) + return err } @@ -60,10 +63,9 @@ type varintReader struct { R io.Reader br io.ByteReader // for reading varints. - lbuf []byte next int pool *pool.BufferPool - lock sync.Locker + lock sync.Mutex max int // the maximal message size (in bytes) this reader handles } @@ -72,26 +74,33 @@ type varintReader struct { // Varints read according to https://golang.org/pkg/encoding/binary/#ReadUvarint // Assumes an equivalent writer on the other side. func NewVarintReader(r io.Reader) ReadCloser { - return NewVarintReaderWithPool(r, pool.GlobalPool) + return NewVarintReaderSize(r, defaultMaxSize) } -// NewVarintReaderWithPool wraps an io.Reader with a varint msgio framed reader. -// The msgio.Reader will read whole messages at a time (using the length). -// Varints read according to https://golang.org/pkg/encoding/binary/#ReadUvarint -// Assumes an equivalent writer on the other side. It uses a given -// pool.BufferPool. +// NewVarintReaderSize is equivalent to NewVarintReader but allows one to +// specify a max message size. +func NewVarintReaderSize(r io.Reader, maxMessageSize int) ReadCloser { + return NewVarintReaderSizeWithPool(r, maxMessageSize, pool.GlobalPool) +} + +// NewVarintReaderWithPool is the same as NewVarintReader but allows one to +// specify a buffer pool. func NewVarintReaderWithPool(r io.Reader, p *pool.BufferPool) ReadCloser { + return NewVarintReaderSizeWithPool(r, defaultMaxSize, p) +} + +// NewVarintReaderWithPool is the same as NewVarintReader but allows one to +// specify a buffer pool and a max message size. +func NewVarintReaderSizeWithPool(r io.Reader, maxMessageSize int, p *pool.BufferPool) ReadCloser { if p == nil { panic("nil pool") } return &varintReader{ R: r, br: &simpleByteReader{R: r}, - lbuf: make([]byte, binary.MaxVarintLen64), next: -1, pool: p, - lock: new(sync.Mutex), - max: defaultMaxSize, + max: maxMessageSize, } } @@ -168,15 +177,11 @@ func (s *varintReader) Close() error { type simpleByteReader struct { R io.Reader - buf []byte + buf [1]byte } func (r *simpleByteReader) ReadByte() (c byte, err error) { - if r.buf == nil { - r.buf = make([]byte, 1) - } - - if _, err := io.ReadFull(r.R, r.buf); err != nil { + if _, err := io.ReadFull(r.R, r.buf[:]); err != nil { return 0, err } return r.buf[0], nil diff --git a/vendor/github.com/spacemonkeygo/openssl/.gitignore b/vendor/github.com/libp2p/go-openssl/.gitignore similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/.gitignore rename to vendor/github.com/libp2p/go-openssl/.gitignore diff --git a/vendor/github.com/spacemonkeygo/openssl/AUTHORS b/vendor/github.com/libp2p/go-openssl/AUTHORS similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/AUTHORS rename to vendor/github.com/libp2p/go-openssl/AUTHORS diff --git a/vendor/github.com/spacemonkeygo/openssl/LICENSE b/vendor/github.com/libp2p/go-openssl/LICENSE similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/LICENSE rename to vendor/github.com/libp2p/go-openssl/LICENSE diff --git a/vendor/github.com/spacemonkeygo/openssl/README.md b/vendor/github.com/libp2p/go-openssl/README.md similarity index 93% rename from vendor/github.com/spacemonkeygo/openssl/README.md rename to vendor/github.com/libp2p/go-openssl/README.md index 854df05ae..b3f1ac2ef 100644 --- a/vendor/github.com/spacemonkeygo/openssl/README.md +++ b/vendor/github.com/libp2p/go-openssl/README.md @@ -1,6 +1,6 @@ # OpenSSL bindings for Go -Please see http://godoc.org/github.com/spacemonkeygo/openssl for more info +Please see http://godoc.org/github.com/libp2p/go-openssl for more info ### License diff --git a/vendor/github.com/spacemonkeygo/openssl/bio.go b/vendor/github.com/libp2p/go-openssl/bio.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/bio.go rename to vendor/github.com/libp2p/go-openssl/bio.go diff --git a/vendor/github.com/spacemonkeygo/openssl/build.go b/vendor/github.com/libp2p/go-openssl/build.go similarity index 87% rename from vendor/github.com/spacemonkeygo/openssl/build.go rename to vendor/github.com/libp2p/go-openssl/build.go index 5fccc0210..9b813b1cb 100644 --- a/vendor/github.com/spacemonkeygo/openssl/build.go +++ b/vendor/github.com/libp2p/go-openssl/build.go @@ -16,8 +16,8 @@ package openssl -// #cgo linux windows pkg-config: libssl libcrypto -// #cgo linux CFLAGS: -Wno-deprecated-declarations +// #cgo linux windows freebsd openbsd pkg-config: libssl libcrypto +// #cgo linux freebsd openbsd CFLAGS: -Wno-deprecated-declarations // #cgo darwin CFLAGS: -I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/openssl/include -Wno-deprecated-declarations // #cgo darwin LDFLAGS: -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/openssl/lib -lssl -lcrypto // #cgo windows CFLAGS: -DWIN32_LEAN_AND_MEAN diff --git a/vendor/github.com/spacemonkeygo/openssl/build_static.go b/vendor/github.com/libp2p/go-openssl/build_static.go similarity index 86% rename from vendor/github.com/spacemonkeygo/openssl/build_static.go rename to vendor/github.com/libp2p/go-openssl/build_static.go index c84427bcb..84f6abeb5 100644 --- a/vendor/github.com/spacemonkeygo/openssl/build_static.go +++ b/vendor/github.com/libp2p/go-openssl/build_static.go @@ -16,8 +16,8 @@ package openssl -// #cgo linux windows pkg-config: --static libssl libcrypto -// #cgo linux CFLAGS: -Wno-deprecated-declarations +// #cgo linux windows freebsd openbsd pkg-config: --static libssl libcrypto +// #cgo linux freebsd openbsd CFLAGS: -Wno-deprecated-declarations // #cgo darwin CFLAGS: -I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/openssl/include -Wno-deprecated-declarations // #cgo darwin LDFLAGS: -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/openssl/lib -lssl -lcrypto // #cgo windows CFLAGS: -DWIN32_LEAN_AND_MEAN diff --git a/vendor/github.com/spacemonkeygo/openssl/cert.go b/vendor/github.com/libp2p/go-openssl/cert.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/cert.go rename to vendor/github.com/libp2p/go-openssl/cert.go diff --git a/vendor/github.com/spacemonkeygo/openssl/ciphers.go b/vendor/github.com/libp2p/go-openssl/ciphers.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/ciphers.go rename to vendor/github.com/libp2p/go-openssl/ciphers.go diff --git a/vendor/github.com/spacemonkeygo/openssl/ciphers_gcm.go b/vendor/github.com/libp2p/go-openssl/ciphers_gcm.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/ciphers_gcm.go rename to vendor/github.com/libp2p/go-openssl/ciphers_gcm.go diff --git a/vendor/github.com/spacemonkeygo/openssl/conn.go b/vendor/github.com/libp2p/go-openssl/conn.go similarity index 99% rename from vendor/github.com/spacemonkeygo/openssl/conn.go rename to vendor/github.com/libp2p/go-openssl/conn.go index 964551cd8..275803419 100644 --- a/vendor/github.com/spacemonkeygo/openssl/conn.go +++ b/vendor/github.com/libp2p/go-openssl/conn.go @@ -27,7 +27,7 @@ import ( "time" "unsafe" - "github.com/spacemonkeygo/openssl/utils" + "github.com/libp2p/go-openssl/utils" ) var ( diff --git a/vendor/github.com/spacemonkeygo/openssl/ctx.go b/vendor/github.com/libp2p/go-openssl/ctx.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/ctx.go rename to vendor/github.com/libp2p/go-openssl/ctx.go diff --git a/vendor/github.com/spacemonkeygo/openssl/dh.go b/vendor/github.com/libp2p/go-openssl/dh.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/dh.go rename to vendor/github.com/libp2p/go-openssl/dh.go diff --git a/vendor/github.com/spacemonkeygo/openssl/dhparam.go b/vendor/github.com/libp2p/go-openssl/dhparam.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/dhparam.go rename to vendor/github.com/libp2p/go-openssl/dhparam.go diff --git a/vendor/github.com/spacemonkeygo/openssl/digest.go b/vendor/github.com/libp2p/go-openssl/digest.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/digest.go rename to vendor/github.com/libp2p/go-openssl/digest.go diff --git a/vendor/github.com/spacemonkeygo/openssl/engine.go b/vendor/github.com/libp2p/go-openssl/engine.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/engine.go rename to vendor/github.com/libp2p/go-openssl/engine.go diff --git a/vendor/github.com/spacemonkeygo/openssl/fips.go b/vendor/github.com/libp2p/go-openssl/fips.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/fips.go rename to vendor/github.com/libp2p/go-openssl/fips.go diff --git a/vendor/github.com/libp2p/go-openssl/go.mod b/vendor/github.com/libp2p/go-openssl/go.mod new file mode 100644 index 000000000..13d7bed42 --- /dev/null +++ b/vendor/github.com/libp2p/go-openssl/go.mod @@ -0,0 +1,6 @@ +module github.com/libp2p/go-openssl + +require ( + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 + golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect +) diff --git a/vendor/github.com/spacemonkeygo/openssl/go.sum b/vendor/github.com/libp2p/go-openssl/go.sum similarity index 53% rename from vendor/github.com/spacemonkeygo/openssl/go.sum rename to vendor/github.com/libp2p/go-openssl/go.sum index 1b0ecc569..3b2b650f8 100644 --- a/vendor/github.com/spacemonkeygo/openssl/go.sum +++ b/vendor/github.com/libp2p/go-openssl/go.sum @@ -1,2 +1,4 @@ github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/spacemonkeygo/openssl/hmac.go b/vendor/github.com/libp2p/go-openssl/hmac.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/hmac.go rename to vendor/github.com/libp2p/go-openssl/hmac.go diff --git a/vendor/github.com/spacemonkeygo/openssl/hostname.c b/vendor/github.com/libp2p/go-openssl/hostname.c similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/hostname.c rename to vendor/github.com/libp2p/go-openssl/hostname.c diff --git a/vendor/github.com/spacemonkeygo/openssl/hostname.go b/vendor/github.com/libp2p/go-openssl/hostname.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/hostname.go rename to vendor/github.com/libp2p/go-openssl/hostname.go diff --git a/vendor/github.com/spacemonkeygo/openssl/http.go b/vendor/github.com/libp2p/go-openssl/http.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/http.go rename to vendor/github.com/libp2p/go-openssl/http.go diff --git a/vendor/github.com/spacemonkeygo/openssl/init.go b/vendor/github.com/libp2p/go-openssl/init.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/init.go rename to vendor/github.com/libp2p/go-openssl/init.go diff --git a/vendor/github.com/spacemonkeygo/openssl/init_posix.go b/vendor/github.com/libp2p/go-openssl/init_posix.go similarity index 97% rename from vendor/github.com/spacemonkeygo/openssl/init_posix.go rename to vendor/github.com/libp2p/go-openssl/init_posix.go index 2da7f9577..605a24bc9 100644 --- a/vendor/github.com/spacemonkeygo/openssl/init_posix.go +++ b/vendor/github.com/libp2p/go-openssl/init_posix.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux darwin solaris +// +build linux darwin solaris freebsd openbsd // +build !windows package openssl diff --git a/vendor/github.com/spacemonkeygo/openssl/init_windows.go b/vendor/github.com/libp2p/go-openssl/init_windows.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/init_windows.go rename to vendor/github.com/libp2p/go-openssl/init_windows.go diff --git a/vendor/github.com/spacemonkeygo/openssl/key.go b/vendor/github.com/libp2p/go-openssl/key.go similarity index 98% rename from vendor/github.com/spacemonkeygo/openssl/key.go rename to vendor/github.com/libp2p/go-openssl/key.go index 91ea98a7d..3b36fa042 100644 --- a/vendor/github.com/spacemonkeygo/openssl/key.go +++ b/vendor/github.com/libp2p/go-openssl/key.go @@ -85,6 +85,9 @@ type PublicKey interface { // `KeyType() == KeyTypeRSA2` would both have `BaseType() == KeyTypeRSA`. BaseType() NID + // Equal compares the key with the passed in key. + Equal(key PublicKey) bool + evpPKey() *C.EVP_PKEY } @@ -109,6 +112,10 @@ type pKey struct { func (key *pKey) evpPKey() *C.EVP_PKEY { return key.key } +func (key *pKey) Equal(other PublicKey) bool { + return C.EVP_PKEY_cmp(key.key, other.evpPKey()) == 1 +} + func (key *pKey) KeyType() NID { return NID(C.EVP_PKEY_id(key.key)) } diff --git a/vendor/github.com/spacemonkeygo/openssl/mapping.go b/vendor/github.com/libp2p/go-openssl/mapping.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/mapping.go rename to vendor/github.com/libp2p/go-openssl/mapping.go diff --git a/vendor/github.com/spacemonkeygo/openssl/md4.go b/vendor/github.com/libp2p/go-openssl/md4.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/md4.go rename to vendor/github.com/libp2p/go-openssl/md4.go diff --git a/vendor/github.com/spacemonkeygo/openssl/md5.go b/vendor/github.com/libp2p/go-openssl/md5.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/md5.go rename to vendor/github.com/libp2p/go-openssl/md5.go diff --git a/vendor/github.com/spacemonkeygo/openssl/net.go b/vendor/github.com/libp2p/go-openssl/net.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/net.go rename to vendor/github.com/libp2p/go-openssl/net.go diff --git a/vendor/github.com/spacemonkeygo/openssl/nid.go b/vendor/github.com/libp2p/go-openssl/nid.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/nid.go rename to vendor/github.com/libp2p/go-openssl/nid.go diff --git a/vendor/github.com/spacemonkeygo/openssl/pem.go b/vendor/github.com/libp2p/go-openssl/pem.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/pem.go rename to vendor/github.com/libp2p/go-openssl/pem.go diff --git a/vendor/github.com/spacemonkeygo/openssl/sha1.go b/vendor/github.com/libp2p/go-openssl/sha1.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/sha1.go rename to vendor/github.com/libp2p/go-openssl/sha1.go diff --git a/vendor/github.com/spacemonkeygo/openssl/sha256.go b/vendor/github.com/libp2p/go-openssl/sha256.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/sha256.go rename to vendor/github.com/libp2p/go-openssl/sha256.go diff --git a/vendor/github.com/spacemonkeygo/openssl/shim.c b/vendor/github.com/libp2p/go-openssl/shim.c similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/shim.c rename to vendor/github.com/libp2p/go-openssl/shim.c diff --git a/vendor/github.com/spacemonkeygo/openssl/shim.h b/vendor/github.com/libp2p/go-openssl/shim.h similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/shim.h rename to vendor/github.com/libp2p/go-openssl/shim.h diff --git a/vendor/github.com/spacemonkeygo/openssl/sni.c b/vendor/github.com/libp2p/go-openssl/sni.c similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/sni.c rename to vendor/github.com/libp2p/go-openssl/sni.c diff --git a/vendor/github.com/spacemonkeygo/openssl/ssl.go b/vendor/github.com/libp2p/go-openssl/ssl.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/ssl.go rename to vendor/github.com/libp2p/go-openssl/ssl.go diff --git a/vendor/github.com/spacemonkeygo/openssl/tickets.go b/vendor/github.com/libp2p/go-openssl/tickets.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/tickets.go rename to vendor/github.com/libp2p/go-openssl/tickets.go diff --git a/vendor/github.com/spacemonkeygo/openssl/utils/errors.go b/vendor/github.com/libp2p/go-openssl/utils/errors.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/utils/errors.go rename to vendor/github.com/libp2p/go-openssl/utils/errors.go diff --git a/vendor/github.com/spacemonkeygo/openssl/utils/future.go b/vendor/github.com/libp2p/go-openssl/utils/future.go similarity index 100% rename from vendor/github.com/spacemonkeygo/openssl/utils/future.go rename to vendor/github.com/libp2p/go-openssl/utils/future.go diff --git a/vendor/github.com/libp2p/go-tcp-transport/README.md b/vendor/github.com/libp2p/go-tcp-transport/README.md index ce8ad9670..75f5218b9 100644 --- a/vendor/github.com/libp2p/go-tcp-transport/README.md +++ b/vendor/github.com/libp2p/go-tcp-transport/README.md @@ -10,21 +10,119 @@ go-tcp-transport > A libp2p transport implementation for tcp, including reuseport socket options. +`go-tcp-transport` is an implementation of the [libp2p transport +interface][concept-transport] that streams data over TCP/IP sockets. It is +included by default in the main [`go-libp2p`][go-libp2p] "entry point" module. ## Table of Contents -- [Install](#install) -- [Usage](#usage) -- [API](#api) -- [Contribute](#contribute) -- [License](#license) +- [go-tcp-transport](#go-tcp-transport) + - [Table of Contents](#table-of-contents) + - [Install](#install) + - [Usage](#usage) + - [Security and Multiplexing](#security-and-multiplexing) + - [reuseport](#reuseport) + - [Contribute](#contribute) + - [License](#license) ## Install -```sh -make install +`go-tcp-transport` is included as a dependency of `go-libp2p`, which is the most +common libp2p entry point. If you depend on `go-libp2p`, there is generally no +need to explicitly depend on this module. + +`go-tcp-transport` is a standard Go module which can be installed with: + +``` sh +go get github.com/libp2p/go-tcp-transport ``` + +This repo is [gomod](https://github.com/golang/go/wiki/Modules)-compatible, and users of +go 1.11 and later with modules enabled will automatically pull the latest tagged release +by referencing this package. Upgrades to future releases can be managed using `go get`, +or by editing your `go.mod` file as [described by the gomod documentation](https://github.com/golang/go/wiki/Modules#how-to-upgrade-and-downgrade-dependencies). + +## Usage + +TCP is one of the default transports enabled when constructing a standard libp2p +Host, along with [WebSockets](https://github.com/libp2p/go-ws-transport). + +Calling [`libp2p.New`][godoc-libp2p-new] to construct a libp2p Host will enable +the TCP transport, unless you override the default transports by passing in +`Options` to `libp2p.New`. + +To explicitly enable the TCP transport while constructing a host, use the +`libp2p.Transport` option, passing in the `NewTCPTransport` constructor function: + +``` go + +import ( + "context" + + libp2p "github.com/libp2p/go-libp2p" + tcp "github.com/libp2p/go-tcp-transport" +) + +ctx := context.Background() + +// TCP only: +h, err := libp2p.New(ctx, + libp2p.Transport(tcp.NewTCPTransport) +) +``` + +The example above will replace the default transports with a single TCP +transport. To add multiple tranports, use `ChainOptions`: + +``` go +// TCP and QUIC: +h, err := libp2p.New(ctx, + libp2p.ChainOptions( + libp2p.Transport(tcp.NewTCPTransport), + libp2p.Transport(quic.NewTransport)) // see https://github.com/libp2p/go-libp2p-quic-transport +) +``` + +## Addresses + +The TCP transport supports [multiaddrs][multiaddr] that contain a `tcp` +component, provided that there is sufficient addressing information for the IP +layer of the connection. + +Examples: + +| addr | description | +|----------------------------|----------------------------------------------------| +| `/ip4/1.2.3.4/tcp/1234` | IPv4: 1.2.3.4, TCP port 1234 | +| `/ip6/::1/tcp/1234` | IPv6 loopback, TCP port 1234 | +| `/dns4/example.com/tcp/80` | DNS over IPv4, hostname `example.com`, TCP port 80 | + + +Support for IP layer protocols is provided by the +[go-multiaddr-net](https://github.com/multiformats/go-multiaddr-net) module. + +## Security and Multiplexing + +Because TCP lacks native connection security and stream multiplexing facilities, +the TCP transport uses a [transport upgrader][transport-upgrader] to provide +those features. The transport upgrader negotiates transport security and +multiplexing for each connection according to the protocols supported by each +party. + +## reuseport + +The [`SO_REUSEPORT`][explain-reuseport] socket option allows multiple processes +or threads to bind to the same TCP port, provided that all of them set the +socket option. This has some performance benefits, and it can potentially assist +in NAT traversal by only requiring one port to be accessible for many +connections. + +The reuseport functionality is provided by a seperate module, +[go-reuseport-transport](https://github.com/libp2p/go-reuseport-transport). It +is enabled by default, but can be disabled at runtime by setting the +`LIBP2P_TCP_REUSEPORT` environment variable to `false` or `0`. + ## Contribute PRs are welcome! @@ -38,3 +136,12 @@ MIT © Jeromy Johnson --- The last gx published version of this module was: 2.0.28: QmTGiDkw4eeKq31wwpQRk5GwWiReaxrcTQLuCCLWgfKo5M + + +[go-libp2p]: https://github.com/libp2p/go-libp2p +[concept-transport]: https://docs.libp2p.io/concepts/transport/ +[interface-host]: https://github.com/libp2p/go-libp2p-core/blob/master/host/host.go +[godoc-libp2p-new]: https://godoc.org/github.com/libp2p/go-libp2p#New +[transport-upgrader]: https://github.com/libp2p/go-libp2p-transport-upgrader +[explain-reuseport]: https://lwn.net/Articles/542629/ +[multiaddr]: https://github.com/multiformats/multiaddr diff --git a/vendor/github.com/libp2p/go-tcp-transport/go.mod b/vendor/github.com/libp2p/go-tcp-transport/go.mod index acfb03f49..67775ead8 100644 --- a/vendor/github.com/libp2p/go-tcp-transport/go.mod +++ b/vendor/github.com/libp2p/go-tcp-transport/go.mod @@ -2,14 +2,15 @@ module github.com/libp2p/go-tcp-transport require ( github.com/ipfs/go-log v0.0.1 - github.com/libp2p/go-libp2p-core v0.0.1 + github.com/libp2p/go-libp2p-core v0.2.2 github.com/libp2p/go-libp2p-mplex v0.2.1 - github.com/libp2p/go-libp2p-testing v0.0.3 + github.com/libp2p/go-libp2p-testing v0.1.0 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 github.com/libp2p/go-reuseport v0.0.1 github.com/libp2p/go-reuseport-transport v0.0.2 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-fmt v0.0.1 - github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/multiformats/go-multihash v0.0.5 // indirect + github.com/multiformats/go-multiaddr v0.1.1 + github.com/multiformats/go-multiaddr-fmt v0.1.0 + github.com/multiformats/go-multiaddr-net v0.1.0 ) + +go 1.12 diff --git a/vendor/github.com/libp2p/go-tcp-transport/go.sum b/vendor/github.com/libp2p/go-tcp-transport/go.sum index b81940b2b..1c3b55b86 100644 --- a/vendor/github.com/libp2p/go-tcp-transport/go.sum +++ b/vendor/github.com/libp2p/go-tcp-transport/go.sum @@ -1,53 +1,83 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.2.0 h1:ycFtuNwtZBAJSxzaHbyv6NjG3Yj5Nmra1csHaQ3zwaw= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= github.com/libp2p/go-libp2p-mplex v0.2.0 h1:vnR+/fUnL5d2kTB1Lfce1KVSP+bCCy2aJIvqvb9cFqE= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= @@ -55,22 +85,35 @@ github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9 github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1 h1:OJIdWOWYe2l5PQNgimGtuwHY8nDskvJ5vvs//YnzRLs= @@ -84,19 +127,25 @@ github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZp github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0 h1:fkISCUNDb3xIpCcI6BGlPsQE+ywcxzimOsUnHWnrE74= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1 h1:jQt9c6tDSdQLIlBo4tXYx7QUHCPjxsB1zXcag/2S7zc= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= -github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -112,31 +161,56 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -145,14 +219,30 @@ golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2V golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c h1:vamGzbGri8IKo20MQncCuljcQ5uAO6kaCeawQPVblAI= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-ws-transport/README.md b/vendor/github.com/libp2p/go-ws-transport/README.md index e9c52a0d9..541a6ce39 100644 --- a/vendor/github.com/libp2p/go-ws-transport/README.md +++ b/vendor/github.com/libp2p/go-ws-transport/README.md @@ -8,10 +8,33 @@ [![Coverage Status](https://coveralls.io/repos/github/libp2p/go-ws-transport/badge.svg?branch=master)](https://coveralls.io/github/libp2p/go-ws-transport?branch=master) [![Build Status](https://travis-ci.org/libp2p/go-ws-transport.svg?branch=master)](https://travis-ci.org/libp2p/go-ws-transport) -> go-libp2p websocket transport +> A libp2p transport implementation using WebSockets + +`go-ws-transport` is an implementation of the [libp2p transport +interface][concept-transport] that streams data over +[WebSockets][spec-websockets], which are themselves layered over TCP/IP. It is +included by default in the main [`go-libp2p`][go-libp2p] "entry point" module. + +## Table of Contents + +- [go-ws-transport](#go-ws-transport) + - [Table of Contents](#table-of-contents) + - [Install](#install) + - [Usage](#usage) + - [Addresses](#addresses) + - [Security and Multiplexing](#security-and-multiplexing) + - [Contribute](#contribute) + - [Want to hack on IPFS?](#want-to-hack-on-ipfs) + - [License](#license) ## Install +`go-ws-transport` is included as a dependency of `go-libp2p`, which is the most +common libp2p entry point. If you depend on `go-libp2p`, there is generally no +need to explicitly depend on this module. + +`go-ws-transport` is a standard Go module which can be installed with: + ```sh > go get github.com/libp2p/go-ws-transport ``` @@ -23,16 +46,85 @@ or by editing your `go.mod` file as [described by the gomod documentation](https ## Usage +WebSockets are one of the default transports enabled when constructing a standard libp2p +Host, along with [TCP](https://github.com/libp2p/go-tcp-transport). + +Calling [`libp2p.New`][godoc-libp2p-new] to construct a libp2p Host will enable +the WebSocket transport, unless you override the default transports by passing in +`Options` to `libp2p.New`. + +To explicitly enable the WebSocket transport while constructing a host, use the +`libp2p.Transport` option, passing in the `ws.New` constructor function: + +``` go + +import ( + "context" + + libp2p "github.com/libp2p/go-libp2p" + ws "github.com/libp2p/go-ws-transport" +) + +ctx := context.Background() + +// WebSockets only: +h, err := libp2p.New(ctx, + libp2p.Transport(ws.New) +) +``` + +The example above will replace the default transports with a single WebSocket +transport. To add multiple tranports, use `ChainOptions`: + +``` go +// WebSockets and QUIC: +h, err := libp2p.New(ctx, + libp2p.ChainOptions( + libp2p.Transport(ws.New), + libp2p.Transport(quic.NewTransport)) // see https://github.com/libp2p/go-libp2p-quic-transport +) +``` + +## Addresses + +The WebSocket transport supports [multiaddrs][multiaddr] that contain a `ws` +component, which is encapsulated within (or layered onto) another valid TCP +multiaddr. + +Examples: + +| addr | description | +|-------------------------------|----------------------------------------------------| +| `/ip4/1.2.3.4/tcp/1234/ws` | IPv4: 1.2.3.4, TCP port 1234 | +| `/ip6/::1/tcp/1234/ws` | IPv6 loopback, TCP port 1234 | +| `/dns4/example.com/tcp/80/ws` | DNS over IPv4, hostname `example.com`, TCP port 80 | + +Notice that the `/ws` multiaddr component contextualizes an existing TCP/IP +multiaddr and does not require any additional addressing information. + +## Security and Multiplexing + +While the WebSocket spec defines a `wss` URI scheme for encrypted WebSocket +connections, support for `wss` URIs relies on TLS, which wraps the WebSocket +connection in a similar manner to TLS-protected HTTP traffic. + +As libp2p does not integrate with the TLS Certificate Authority infrastructure +by design, security for WebSockets is provided by a [transport +upgrader][transport-upgrader]. The transport upgrader negotiates transport +security for each connection according to the protocols supported by each party. + +The transport upgrader also negotiates a stream multiplexing protocol to allow +many bidirectional streams to coexist on a single WebSocket connection. ## Contribute Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/go-ws-transport/issues)! -This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). +This repository falls under the libp2p [Code of Conduct](https://github.com/libp2p/community/blob/master/code-of-conduct.md). -### Want to hack on IPFS? +### Want to hack on libp2p? -[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) +[![](https://cdn.rawgit.com/libp2p/community/master/img/contribute.gif)](https://github.com/libp2p/community/blob/master/CONTRIBUTE.md) ## License @@ -41,3 +133,12 @@ MIT --- The last gx published version of this module was: 2.0.27: QmaSWc4ox6SZQF6DHZvDuM9sP1syNajkKuPXmKR1t5BAz5 + + +[go-libp2p]: https://github.com/libp2p/go-libp2p +[concept-transport]: https://docs.libp2p.io/concepts/transport/ +[interface-host]: https://github.com/libp2p/go-libp2p-core/blob/master/host/host.go +[godoc-libp2p-new]: https://godoc.org/github.com/libp2p/go-libp2p#New +[transport-upgrader]: https://github.com/libp2p/go-libp2p-transport-upgrader +[multiaddr]: https://github.com/multiformats/multiaddr +[spec-websockets]: https://tools.ietf.org/html/rfc6455 diff --git a/vendor/github.com/libp2p/go-ws-transport/go.mod b/vendor/github.com/libp2p/go-ws-transport/go.mod index b25b7dff3..b9dac119b 100644 --- a/vendor/github.com/libp2p/go-ws-transport/go.mod +++ b/vendor/github.com/libp2p/go-ws-transport/go.mod @@ -1,12 +1,14 @@ module github.com/libp2p/go-ws-transport require ( - github.com/gorilla/websocket v1.4.0 - github.com/libp2p/go-libp2p-core v0.0.1 - github.com/libp2p/go-libp2p-mplex v0.2.0 - github.com/libp2p/go-libp2p-testing v0.0.3 + github.com/gorilla/websocket v1.4.1 + github.com/libp2p/go-libp2p-core v0.2.2 + github.com/libp2p/go-libp2p-mplex v0.2.1 + github.com/libp2p/go-libp2p-testing v0.1.0 github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 - github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-net v0.0.1 - github.com/whyrusleeping/mafmt v1.2.8 + github.com/multiformats/go-multiaddr v0.1.1 + github.com/multiformats/go-multiaddr-fmt v0.1.0 + github.com/multiformats/go-multiaddr-net v0.1.0 ) + +go 1.12 diff --git a/vendor/github.com/libp2p/go-ws-transport/go.sum b/vendor/github.com/libp2p/go-ws-transport/go.sum index ad6d7b54b..07c1e17de 100644 --- a/vendor/github.com/libp2p/go-ws-transport/go.sum +++ b/vendor/github.com/libp2p/go-ws-transport/go.sum @@ -1,83 +1,141 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p-core v0.0.1 h1:HSTZtFIq/W5Ue43Zw+uWZyy2Vl5WtF0zDjKN8/DT/1I= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2 h1:Sv1ggdoMx9c7v7FOFkR7agraHCnAgqYsXrU1ARSRUMs= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= github.com/libp2p/go-libp2p-mplex v0.2.0 h1:vnR+/fUnL5d2kTB1Lfce1KVSP+bCCy2aJIvqvb9cFqE= github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= +github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= +github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0 h1:WaFRj/t3HdMZGNZqnU2pS7pDRBmMeoDx7/HDNpeyT9U= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-mplex v0.0.3 h1:YiMaevQcZtFU6DmKIF8xEO0vaui5kM5HJ1V1xkWQv14= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= +github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= +github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1 h1:OJIdWOWYe2l5PQNgimGtuwHY8nDskvJ5vvs//YnzRLs= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1 h1:jQt9c6tDSdQLIlBo4tXYx7QUHCPjxsB1zXcag/2S7zc= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= @@ -89,38 +147,87 @@ github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= -github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= -github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c h1:vamGzbGri8IKo20MQncCuljcQ5uAO6kaCeawQPVblAI= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/libp2p/go-ws-transport/websocket.go b/vendor/github.com/libp2p/go-ws-transport/websocket.go index 972681a64..941edac6b 100644 --- a/vendor/github.com/libp2p/go-ws-transport/websocket.go +++ b/vendor/github.com/libp2p/go-ws-transport/websocket.go @@ -3,7 +3,6 @@ package websocket import ( "context" - "fmt" "net" "net/http" "net/url" @@ -15,16 +14,14 @@ import ( ws "github.com/gorilla/websocket" ma "github.com/multiformats/go-multiaddr" + mafmt "github.com/multiformats/go-multiaddr-fmt" manet "github.com/multiformats/go-multiaddr-net" - mafmt "github.com/whyrusleeping/mafmt" ) // WsProtocol is the multiaddr protocol definition for this transport. -var WsProtocol = ma.Protocol{ - Code: 477, - Name: "ws", - VCode: ma.CodeToVarint(477), -} +// +// Deprecated: use `ma.ProtocolWithCode(ma.P_WS) +var WsProtocol = ma.ProtocolWithCode(ma.P_WS) // WsFmt is multiaddr formatter for WsProtocol var WsFmt = mafmt.And(mafmt.TCP, mafmt.Base(WsProtocol.Code)) @@ -46,11 +43,6 @@ var upgrader = ws.Upgrader{ } func init() { - err := ma.AddProtocol(WsProtocol) - if err != nil { - panic(fmt.Errorf("error registering websocket protocol: %s", err)) - } - manet.RegisterNetCodec(WsCodec) } diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml new file mode 100644 index 000000000..5c9c2a30f --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL diff --git a/vendor/github.com/mattn/go-runewidth/LICENSE b/vendor/github.com/mattn/go-runewidth/LICENSE new file mode 100644 index 000000000..91b5cef30 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +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/mattn/go-runewidth/README.mkd b/vendor/github.com/mattn/go-runewidth/README.mkd new file mode 100644 index 000000000..66663a94b --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/README.mkd @@ -0,0 +1,27 @@ +go-runewidth +============ + +[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) +[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) +[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) +[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) + +Provides functions to get fixed width of the character or string. + +Usage +----- + +```go +runewidth.StringWidth("つのだ☆HIRO") == 12 +``` + + +Author +------ + +Yasuhiro Matsumoto + +License +------- + +under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go new file mode 100644 index 000000000..82568a1bb --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -0,0 +1,1235 @@ +package runewidth + +import "os" + +var ( + // EastAsianWidth will be set true if the current locale is CJK + EastAsianWidth bool + + // DefaultCondition is a condition in current locale + DefaultCondition = &Condition{EastAsianWidth} +) + +func init() { + env := os.Getenv("RUNEWIDTH_EASTASIAN") + if env == "" { + EastAsianWidth = IsEastAsian() + } else { + EastAsianWidth = env == "1" + } +} + +type interval struct { + first rune + last rune +} + +type table []interval + +func inTables(r rune, ts ...table) bool { + for _, t := range ts { + if inTable(r, t) { + return true + } + } + return false +} + +func inTable(r rune, t table) bool { + // func (t table) IncludesRune(r rune) bool { + if r < t[0].first { + return false + } + + bot := 0 + top := len(t) - 1 + for top >= bot { + mid := (bot + top) / 2 + + switch { + case t[mid].last < r: + bot = mid + 1 + case t[mid].first > r: + top = mid - 1 + default: + return true + } + } + + return false +} + +var private = table{ + {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, +} + +var nonprint = table{ + {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, + {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, + {0x2028, 0x2029}, + {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, +} + +var combining = table{ + {0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, + {0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F}, + {0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4}, + {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711}, + {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, + {0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827}, + {0x0829, 0x082D}, {0x0859, 0x085B}, {0x08D4, 0x08E1}, + {0x08E3, 0x0903}, {0x093A, 0x093C}, {0x093E, 0x094F}, + {0x0951, 0x0957}, {0x0962, 0x0963}, {0x0981, 0x0983}, + {0x09BC, 0x09BC}, {0x09BE, 0x09C4}, {0x09C7, 0x09C8}, + {0x09CB, 0x09CD}, {0x09D7, 0x09D7}, {0x09E2, 0x09E3}, + {0x0A01, 0x0A03}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A83}, + {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, + {0x0ACB, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B03}, + {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48}, + {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B62, 0x0B63}, + {0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C03}, + {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C62, 0x0C63}, {0x0C81, 0x0C83}, + {0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8}, + {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, {0x0CE2, 0x0CE3}, + {0x0D01, 0x0D03}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63}, + {0x0D82, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, + {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3}, + {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, + {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, + {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F}, + {0x0F71, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102B, 0x103E}, + {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064}, + {0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D}, + {0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F}, + {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, + {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, + {0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9}, + {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B}, + {0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ABE}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44}, + {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD}, + {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2}, + {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF2, 0x1CF4}, + {0x1CF8, 0x1CF9}, {0x1DC0, 0x1DF5}, {0x1DFB, 0x1DFF}, + {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, + {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A}, + {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, + {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806}, + {0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA880, 0xA881}, + {0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA926, 0xA92D}, + {0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0}, + {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43}, + {0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0}, + {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF}, + {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6}, + {0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E}, + {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, + {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, + {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x11000, 0x11002}, + {0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA}, + {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11173, 0x11173}, + {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111CA, 0x111CC}, + {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA}, + {0x11300, 0x11303}, {0x1133C, 0x1133C}, {0x1133E, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, + {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, + {0x11435, 0x11446}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, + {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, + {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F51, 0x16F7E}, + {0x16F8F, 0x16F92}, {0x1BC9D, 0x1BC9E}, {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF}, +} + +var doublewidth = table{ + {0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A}, + {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3}, + {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653}, + {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, + {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, + {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, + {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, + {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B}, + {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E}, + {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, + {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, + {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, + {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, + {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, + {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, + {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, + {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE0}, {0x17000, 0x187EC}, + {0x18800, 0x18AF2}, {0x1B000, 0x1B001}, {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, + {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, + {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, + {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, + {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D2}, {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, + {0x1F910, 0x1F91E}, {0x1F920, 0x1F927}, {0x1F930, 0x1F930}, + {0x1F933, 0x1F93E}, {0x1F940, 0x1F94B}, {0x1F950, 0x1F95E}, + {0x1F980, 0x1F991}, {0x1F9C0, 0x1F9C0}, {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD}, +} + +var ambiguous = table{ + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, + {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, + {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, + {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, + {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, + {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, + {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, + {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, + {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, + {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, + {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, + {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, + {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, + {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, + {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, + {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, + {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, + {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, + {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, + {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, + {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, + {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, + {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, + {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, + {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, + {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, + {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, + {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, + {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, + {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, + {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, + {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, + {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, + {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, + {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, + {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, + {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, + {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, + {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, + {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, + {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, + {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, + {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, + {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, + {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, + {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, + {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, + {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, + {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, +} + +var emoji = table{ + {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F321}, {0x1F324, 0x1F32C}, + {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F396, 0x1F397}, + {0x1F399, 0x1F39B}, {0x1F39E, 0x1F39F}, {0x1F3CB, 0x1F3CE}, + {0x1F3D4, 0x1F3DF}, {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3F7}, + {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FD}, + {0x1F549, 0x1F54A}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F579}, + {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, + {0x1F5A5, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2}, + {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3}, + {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3}, + {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3}, + {0x1F5FA, 0x1F5FA}, {0x1F6CB, 0x1F6CF}, {0x1F6E0, 0x1F6E5}, + {0x1F6E9, 0x1F6E9}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F3}, +} + +var notassigned = table{ + {0x0378, 0x0379}, {0x0380, 0x0383}, {0x038B, 0x038B}, + {0x038D, 0x038D}, {0x03A2, 0x03A2}, {0x0530, 0x0530}, + {0x0557, 0x0558}, {0x0560, 0x0560}, {0x0588, 0x0588}, + {0x058B, 0x058C}, {0x0590, 0x0590}, {0x05C8, 0x05CF}, + {0x05EB, 0x05EF}, {0x05F5, 0x05FF}, {0x061D, 0x061D}, + {0x070E, 0x070E}, {0x074B, 0x074C}, {0x07B2, 0x07BF}, + {0x07FB, 0x07FF}, {0x082E, 0x082F}, {0x083F, 0x083F}, + {0x085C, 0x085D}, {0x085F, 0x089F}, {0x08B5, 0x08B5}, + {0x08BE, 0x08D3}, {0x0984, 0x0984}, {0x098D, 0x098E}, + {0x0991, 0x0992}, {0x09A9, 0x09A9}, {0x09B1, 0x09B1}, + {0x09B3, 0x09B5}, {0x09BA, 0x09BB}, {0x09C5, 0x09C6}, + {0x09C9, 0x09CA}, {0x09CF, 0x09D6}, {0x09D8, 0x09DB}, + {0x09DE, 0x09DE}, {0x09E4, 0x09E5}, {0x09FC, 0x0A00}, + {0x0A04, 0x0A04}, {0x0A0B, 0x0A0E}, {0x0A11, 0x0A12}, + {0x0A29, 0x0A29}, {0x0A31, 0x0A31}, {0x0A34, 0x0A34}, + {0x0A37, 0x0A37}, {0x0A3A, 0x0A3B}, {0x0A3D, 0x0A3D}, + {0x0A43, 0x0A46}, {0x0A49, 0x0A4A}, {0x0A4E, 0x0A50}, + {0x0A52, 0x0A58}, {0x0A5D, 0x0A5D}, {0x0A5F, 0x0A65}, + {0x0A76, 0x0A80}, {0x0A84, 0x0A84}, {0x0A8E, 0x0A8E}, + {0x0A92, 0x0A92}, {0x0AA9, 0x0AA9}, {0x0AB1, 0x0AB1}, + {0x0AB4, 0x0AB4}, {0x0ABA, 0x0ABB}, {0x0AC6, 0x0AC6}, + {0x0ACA, 0x0ACA}, {0x0ACE, 0x0ACF}, {0x0AD1, 0x0ADF}, + {0x0AE4, 0x0AE5}, {0x0AF2, 0x0AF8}, {0x0AFA, 0x0B00}, + {0x0B04, 0x0B04}, {0x0B0D, 0x0B0E}, {0x0B11, 0x0B12}, + {0x0B29, 0x0B29}, {0x0B31, 0x0B31}, {0x0B34, 0x0B34}, + {0x0B3A, 0x0B3B}, {0x0B45, 0x0B46}, {0x0B49, 0x0B4A}, + {0x0B4E, 0x0B55}, {0x0B58, 0x0B5B}, {0x0B5E, 0x0B5E}, + {0x0B64, 0x0B65}, {0x0B78, 0x0B81}, {0x0B84, 0x0B84}, + {0x0B8B, 0x0B8D}, {0x0B91, 0x0B91}, {0x0B96, 0x0B98}, + {0x0B9B, 0x0B9B}, {0x0B9D, 0x0B9D}, {0x0BA0, 0x0BA2}, + {0x0BA5, 0x0BA7}, {0x0BAB, 0x0BAD}, {0x0BBA, 0x0BBD}, + {0x0BC3, 0x0BC5}, {0x0BC9, 0x0BC9}, {0x0BCE, 0x0BCF}, + {0x0BD1, 0x0BD6}, {0x0BD8, 0x0BE5}, {0x0BFB, 0x0BFF}, + {0x0C04, 0x0C04}, {0x0C0D, 0x0C0D}, {0x0C11, 0x0C11}, + {0x0C29, 0x0C29}, {0x0C3A, 0x0C3C}, {0x0C45, 0x0C45}, + {0x0C49, 0x0C49}, {0x0C4E, 0x0C54}, {0x0C57, 0x0C57}, + {0x0C5B, 0x0C5F}, {0x0C64, 0x0C65}, {0x0C70, 0x0C77}, + {0x0C84, 0x0C84}, {0x0C8D, 0x0C8D}, {0x0C91, 0x0C91}, + {0x0CA9, 0x0CA9}, {0x0CB4, 0x0CB4}, {0x0CBA, 0x0CBB}, + {0x0CC5, 0x0CC5}, {0x0CC9, 0x0CC9}, {0x0CCE, 0x0CD4}, + {0x0CD7, 0x0CDD}, {0x0CDF, 0x0CDF}, {0x0CE4, 0x0CE5}, + {0x0CF0, 0x0CF0}, {0x0CF3, 0x0D00}, {0x0D04, 0x0D04}, + {0x0D0D, 0x0D0D}, {0x0D11, 0x0D11}, {0x0D3B, 0x0D3C}, + {0x0D45, 0x0D45}, {0x0D49, 0x0D49}, {0x0D50, 0x0D53}, + {0x0D64, 0x0D65}, {0x0D80, 0x0D81}, {0x0D84, 0x0D84}, + {0x0D97, 0x0D99}, {0x0DB2, 0x0DB2}, {0x0DBC, 0x0DBC}, + {0x0DBE, 0x0DBF}, {0x0DC7, 0x0DC9}, {0x0DCB, 0x0DCE}, + {0x0DD5, 0x0DD5}, {0x0DD7, 0x0DD7}, {0x0DE0, 0x0DE5}, + {0x0DF0, 0x0DF1}, {0x0DF5, 0x0E00}, {0x0E3B, 0x0E3E}, + {0x0E5C, 0x0E80}, {0x0E83, 0x0E83}, {0x0E85, 0x0E86}, + {0x0E89, 0x0E89}, {0x0E8B, 0x0E8C}, {0x0E8E, 0x0E93}, + {0x0E98, 0x0E98}, {0x0EA0, 0x0EA0}, {0x0EA4, 0x0EA4}, + {0x0EA6, 0x0EA6}, {0x0EA8, 0x0EA9}, {0x0EAC, 0x0EAC}, + {0x0EBA, 0x0EBA}, {0x0EBE, 0x0EBF}, {0x0EC5, 0x0EC5}, + {0x0EC7, 0x0EC7}, {0x0ECE, 0x0ECF}, {0x0EDA, 0x0EDB}, + {0x0EE0, 0x0EFF}, {0x0F48, 0x0F48}, {0x0F6D, 0x0F70}, + {0x0F98, 0x0F98}, {0x0FBD, 0x0FBD}, {0x0FCD, 0x0FCD}, + {0x0FDB, 0x0FFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC}, + {0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F}, + {0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F}, + {0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1}, + {0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1}, + {0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311}, + {0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F}, + {0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF}, + {0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D}, + {0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F}, + {0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F}, + {0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF}, + {0x180F, 0x180F}, {0x181A, 0x181F}, {0x1878, 0x187F}, + {0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F}, + {0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943}, + {0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF}, + {0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D}, + {0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F}, + {0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1ABF, 0x1AFF}, + {0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB}, + {0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1CBF}, + {0x1CC8, 0x1CCF}, {0x1CF7, 0x1CF7}, {0x1CFA, 0x1CFF}, + {0x1DF6, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F}, + {0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58}, + {0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E}, + {0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5}, + {0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF1}, + {0x1FF5, 0x1FF5}, {0x1FFF, 0x1FFF}, {0x2065, 0x2065}, + {0x2072, 0x2073}, {0x208F, 0x208F}, {0x209D, 0x209F}, + {0x20BF, 0x20CF}, {0x20F1, 0x20FF}, {0x218C, 0x218F}, + {0x23FF, 0x23FF}, {0x2427, 0x243F}, {0x244B, 0x245F}, + {0x2B74, 0x2B75}, {0x2B96, 0x2B97}, {0x2BBA, 0x2BBC}, + {0x2BC9, 0x2BC9}, {0x2BD2, 0x2BEB}, {0x2BF0, 0x2BFF}, + {0x2C2F, 0x2C2F}, {0x2C5F, 0x2C5F}, {0x2CF4, 0x2CF8}, + {0x2D26, 0x2D26}, {0x2D28, 0x2D2C}, {0x2D2E, 0x2D2F}, + {0x2D68, 0x2D6E}, {0x2D71, 0x2D7E}, {0x2D97, 0x2D9F}, + {0x2DA7, 0x2DA7}, {0x2DAF, 0x2DAF}, {0x2DB7, 0x2DB7}, + {0x2DBF, 0x2DBF}, {0x2DC7, 0x2DC7}, {0x2DCF, 0x2DCF}, + {0x2DD7, 0x2DD7}, {0x2DDF, 0x2DDF}, {0x2E45, 0x2E7F}, + {0x2E9A, 0x2E9A}, {0x2EF4, 0x2EFF}, {0x2FD6, 0x2FEF}, + {0x2FFC, 0x2FFF}, {0x3040, 0x3040}, {0x3097, 0x3098}, + {0x3100, 0x3104}, {0x312E, 0x3130}, {0x318F, 0x318F}, + {0x31BB, 0x31BF}, {0x31E4, 0x31EF}, {0x321F, 0x321F}, + {0x32FF, 0x32FF}, {0x4DB6, 0x4DBF}, {0x9FD6, 0x9FFF}, + {0xA48D, 0xA48F}, {0xA4C7, 0xA4CF}, {0xA62C, 0xA63F}, + {0xA6F8, 0xA6FF}, {0xA7AF, 0xA7AF}, {0xA7B8, 0xA7F6}, + {0xA82C, 0xA82F}, {0xA83A, 0xA83F}, {0xA878, 0xA87F}, + {0xA8C6, 0xA8CD}, {0xA8DA, 0xA8DF}, {0xA8FE, 0xA8FF}, + {0xA954, 0xA95E}, {0xA97D, 0xA97F}, {0xA9CE, 0xA9CE}, + {0xA9DA, 0xA9DD}, {0xA9FF, 0xA9FF}, {0xAA37, 0xAA3F}, + {0xAA4E, 0xAA4F}, {0xAA5A, 0xAA5B}, {0xAAC3, 0xAADA}, + {0xAAF7, 0xAB00}, {0xAB07, 0xAB08}, {0xAB0F, 0xAB10}, + {0xAB17, 0xAB1F}, {0xAB27, 0xAB27}, {0xAB2F, 0xAB2F}, + {0xAB66, 0xAB6F}, {0xABEE, 0xABEF}, {0xABFA, 0xABFF}, + {0xD7A4, 0xD7AF}, {0xD7C7, 0xD7CA}, {0xD7FC, 0xD7FF}, + {0xFA6E, 0xFA6F}, {0xFADA, 0xFAFF}, {0xFB07, 0xFB12}, + {0xFB18, 0xFB1C}, {0xFB37, 0xFB37}, {0xFB3D, 0xFB3D}, + {0xFB3F, 0xFB3F}, {0xFB42, 0xFB42}, {0xFB45, 0xFB45}, + {0xFBC2, 0xFBD2}, {0xFD40, 0xFD4F}, {0xFD90, 0xFD91}, + {0xFDC8, 0xFDEF}, {0xFDFE, 0xFDFF}, {0xFE1A, 0xFE1F}, + {0xFE53, 0xFE53}, {0xFE67, 0xFE67}, {0xFE6C, 0xFE6F}, + {0xFE75, 0xFE75}, {0xFEFD, 0xFEFE}, {0xFF00, 0xFF00}, + {0xFFBF, 0xFFC1}, {0xFFC8, 0xFFC9}, {0xFFD0, 0xFFD1}, + {0xFFD8, 0xFFD9}, {0xFFDD, 0xFFDF}, {0xFFE7, 0xFFE7}, + {0xFFEF, 0xFFF8}, {0xFFFE, 0xFFFF}, {0x1000C, 0x1000C}, + {0x10027, 0x10027}, {0x1003B, 0x1003B}, {0x1003E, 0x1003E}, + {0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF}, + {0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F}, + {0x1019C, 0x1019F}, {0x101A1, 0x101CF}, {0x101FE, 0x1027F}, + {0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF}, + {0x10324, 0x1032F}, {0x1034B, 0x1034F}, {0x1037B, 0x1037F}, + {0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7}, + {0x104FC, 0x104FF}, {0x10528, 0x1052F}, {0x10564, 0x1056E}, + {0x10570, 0x105FF}, {0x10737, 0x1073F}, {0x10756, 0x1075F}, + {0x10768, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809}, + {0x10836, 0x10836}, {0x10839, 0x1083B}, {0x1083D, 0x1083E}, + {0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF}, + {0x108F3, 0x108F3}, {0x108F6, 0x108FA}, {0x1091C, 0x1091E}, + {0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B}, + {0x10A14, 0x10A14}, {0x10A18, 0x10A18}, {0x10A34, 0x10A37}, + {0x10A3B, 0x10A3E}, {0x10A48, 0x10A4F}, {0x10A59, 0x10A5F}, + {0x10AA0, 0x10ABF}, {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF}, + {0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF}, + {0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, {0x10CF3, 0x10CF9}, + {0x10D00, 0x10E5F}, {0x10E7F, 0x10FFF}, {0x1104E, 0x11051}, + {0x11070, 0x1107E}, {0x110C2, 0x110CF}, {0x110E9, 0x110EF}, + {0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11144, 0x1114F}, + {0x11177, 0x1117F}, {0x111CE, 0x111CF}, {0x111E0, 0x111E0}, + {0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x1123F, 0x1127F}, + {0x11287, 0x11287}, {0x11289, 0x11289}, {0x1128E, 0x1128E}, + {0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E}, + {0x11311, 0x11312}, {0x11329, 0x11329}, {0x11331, 0x11331}, + {0x11334, 0x11334}, {0x1133A, 0x1133B}, {0x11345, 0x11346}, + {0x11349, 0x1134A}, {0x1134E, 0x1134F}, {0x11351, 0x11356}, + {0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F}, + {0x11375, 0x113FF}, {0x1145A, 0x1145A}, {0x1145C, 0x1145C}, + {0x1145E, 0x1147F}, {0x114C8, 0x114CF}, {0x114DA, 0x1157F}, + {0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F}, + {0x1165A, 0x1165F}, {0x1166D, 0x1167F}, {0x116B8, 0x116BF}, + {0x116CA, 0x116FF}, {0x1171A, 0x1171C}, {0x1172C, 0x1172F}, + {0x11740, 0x1189F}, {0x118F3, 0x118FE}, {0x11900, 0x11ABF}, + {0x11AF9, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37}, + {0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, {0x11C90, 0x11C91}, + {0x11CA8, 0x11CA8}, {0x11CB7, 0x11FFF}, {0x1239A, 0x123FF}, + {0x1246F, 0x1246F}, {0x12475, 0x1247F}, {0x12544, 0x12FFF}, + {0x1342F, 0x143FF}, {0x14647, 0x167FF}, {0x16A39, 0x16A3F}, + {0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16A70, 0x16ACF}, + {0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F}, + {0x16B5A, 0x16B5A}, {0x16B62, 0x16B62}, {0x16B78, 0x16B7C}, + {0x16B90, 0x16EFF}, {0x16F45, 0x16F4F}, {0x16F7F, 0x16F8E}, + {0x16FA0, 0x16FDF}, {0x16FE1, 0x16FFF}, {0x187ED, 0x187FF}, + {0x18AF3, 0x1AFFF}, {0x1B002, 0x1BBFF}, {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B}, + {0x1BCA4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, {0x1D127, 0x1D128}, + {0x1D1E9, 0x1D1FF}, {0x1D246, 0x1D2FF}, {0x1D357, 0x1D35F}, + {0x1D372, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D}, + {0x1D4A0, 0x1D4A1}, {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8}, + {0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C}, + {0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, {0x1D53A, 0x1D53A}, + {0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549}, + {0x1D551, 0x1D551}, {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD}, + {0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DFFF}, + {0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, {0x1E02B, 0x1E7FF}, {0x1E8C5, 0x1E8C6}, + {0x1E8D7, 0x1E8FF}, {0x1E94B, 0x1E94F}, {0x1E95A, 0x1E95D}, + {0x1E960, 0x1EDFF}, {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20}, + {0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A}, + {0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, {0x1EE48, 0x1EE48}, + {0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50}, + {0x1EE53, 0x1EE53}, {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58}, + {0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66}, + {0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, {0x1EE78, 0x1EE78}, + {0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A}, + {0x1EE9C, 0x1EEA0}, {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA}, + {0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0}, + {0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F10D, 0x1F10F}, + {0x1F12F, 0x1F12F}, {0x1F16C, 0x1F16F}, {0x1F1AD, 0x1F1E5}, + {0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F}, + {0x1F252, 0x1F2FF}, {0x1F6D3, 0x1F6DF}, {0x1F6ED, 0x1F6EF}, + {0x1F6F7, 0x1F6FF}, {0x1F774, 0x1F77F}, {0x1F7D5, 0x1F7FF}, + {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, + {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F90F}, {0x1F91F, 0x1F91F}, + {0x1F928, 0x1F92F}, {0x1F931, 0x1F932}, {0x1F93F, 0x1F93F}, + {0x1F94C, 0x1F94F}, {0x1F95F, 0x1F97F}, {0x1F992, 0x1F9BF}, + {0x1F9C1, 0x1FFFF}, {0x2A6D7, 0x2A6FF}, {0x2B735, 0x2B73F}, + {0x2B81E, 0x2B81F}, {0x2CEA2, 0x2F7FF}, {0x2FA1E, 0xE0000}, + {0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, {0xE01F0, 0xEFFFF}, + {0xFFFFE, 0xFFFFF}, +} + +var neutral = table{ + {0x0000, 0x001F}, {0x007F, 0x007F}, {0x0080, 0x009F}, + {0x00A0, 0x00A0}, {0x00A9, 0x00A9}, {0x00AB, 0x00AB}, + {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, {0x00C0, 0x00C5}, + {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, {0x00D9, 0x00DD}, + {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, {0x00EB, 0x00EB}, + {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, {0x00F4, 0x00F6}, + {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, {0x00FF, 0x00FF}, + {0x0100, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, + {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, + {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, + {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, + {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, + {0x016C, 0x017F}, {0x0180, 0x01BA}, {0x01BB, 0x01BB}, + {0x01BC, 0x01BF}, {0x01C0, 0x01C3}, {0x01C4, 0x01CD}, + {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, {0x01D3, 0x01D3}, + {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, {0x01D9, 0x01D9}, + {0x01DB, 0x01DB}, {0x01DD, 0x024F}, {0x0250, 0x0250}, + {0x0252, 0x0260}, {0x0262, 0x0293}, {0x0294, 0x0294}, + {0x0295, 0x02AF}, {0x02B0, 0x02C1}, {0x02C2, 0x02C3}, + {0x02C5, 0x02C5}, {0x02C6, 0x02C6}, {0x02C8, 0x02C8}, + {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, {0x02D1, 0x02D1}, + {0x02D2, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, + {0x02E0, 0x02E4}, {0x02E5, 0x02EB}, {0x02EC, 0x02EC}, + {0x02ED, 0x02ED}, {0x02EE, 0x02EE}, {0x02EF, 0x02FF}, + {0x0370, 0x0373}, {0x0374, 0x0374}, {0x0375, 0x0375}, + {0x0376, 0x0377}, {0x037A, 0x037A}, {0x037B, 0x037D}, + {0x037E, 0x037E}, {0x037F, 0x037F}, {0x0384, 0x0385}, + {0x0386, 0x0386}, {0x0387, 0x0387}, {0x0388, 0x038A}, + {0x038C, 0x038C}, {0x038E, 0x0390}, {0x03AA, 0x03B0}, + {0x03C2, 0x03C2}, {0x03CA, 0x03F5}, {0x03F6, 0x03F6}, + {0x03F7, 0x03FF}, {0x0400, 0x0400}, {0x0402, 0x040F}, + {0x0450, 0x0450}, {0x0452, 0x0481}, {0x0482, 0x0482}, + {0x0483, 0x0487}, {0x0488, 0x0489}, {0x048A, 0x04FF}, + {0x0500, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x0559}, + {0x055A, 0x055F}, {0x0561, 0x0587}, {0x0589, 0x0589}, + {0x058A, 0x058A}, {0x058D, 0x058E}, {0x058F, 0x058F}, + {0x0591, 0x05BD}, {0x05BE, 0x05BE}, {0x05BF, 0x05BF}, + {0x05C0, 0x05C0}, {0x05C1, 0x05C2}, {0x05C3, 0x05C3}, + {0x05C4, 0x05C5}, {0x05C6, 0x05C6}, {0x05C7, 0x05C7}, + {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x05F3, 0x05F4}, + {0x0600, 0x0605}, {0x0606, 0x0608}, {0x0609, 0x060A}, + {0x060B, 0x060B}, {0x060C, 0x060D}, {0x060E, 0x060F}, + {0x0610, 0x061A}, {0x061B, 0x061B}, {0x061C, 0x061C}, + {0x061E, 0x061F}, {0x0620, 0x063F}, {0x0640, 0x0640}, + {0x0641, 0x064A}, {0x064B, 0x065F}, {0x0660, 0x0669}, + {0x066A, 0x066D}, {0x066E, 0x066F}, {0x0670, 0x0670}, + {0x0671, 0x06D3}, {0x06D4, 0x06D4}, {0x06D5, 0x06D5}, + {0x06D6, 0x06DC}, {0x06DD, 0x06DD}, {0x06DE, 0x06DE}, + {0x06DF, 0x06E4}, {0x06E5, 0x06E6}, {0x06E7, 0x06E8}, + {0x06E9, 0x06E9}, {0x06EA, 0x06ED}, {0x06EE, 0x06EF}, + {0x06F0, 0x06F9}, {0x06FA, 0x06FC}, {0x06FD, 0x06FE}, + {0x06FF, 0x06FF}, {0x0700, 0x070D}, {0x070F, 0x070F}, + {0x0710, 0x0710}, {0x0711, 0x0711}, {0x0712, 0x072F}, + {0x0730, 0x074A}, {0x074D, 0x074F}, {0x0750, 0x077F}, + {0x0780, 0x07A5}, {0x07A6, 0x07B0}, {0x07B1, 0x07B1}, + {0x07C0, 0x07C9}, {0x07CA, 0x07EA}, {0x07EB, 0x07F3}, + {0x07F4, 0x07F5}, {0x07F6, 0x07F6}, {0x07F7, 0x07F9}, + {0x07FA, 0x07FA}, {0x0800, 0x0815}, {0x0816, 0x0819}, + {0x081A, 0x081A}, {0x081B, 0x0823}, {0x0824, 0x0824}, + {0x0825, 0x0827}, {0x0828, 0x0828}, {0x0829, 0x082D}, + {0x0830, 0x083E}, {0x0840, 0x0858}, {0x0859, 0x085B}, + {0x085E, 0x085E}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD}, + {0x08D4, 0x08E1}, {0x08E2, 0x08E2}, {0x08E3, 0x08FF}, + {0x0900, 0x0902}, {0x0903, 0x0903}, {0x0904, 0x0939}, + {0x093A, 0x093A}, {0x093B, 0x093B}, {0x093C, 0x093C}, + {0x093D, 0x093D}, {0x093E, 0x0940}, {0x0941, 0x0948}, + {0x0949, 0x094C}, {0x094D, 0x094D}, {0x094E, 0x094F}, + {0x0950, 0x0950}, {0x0951, 0x0957}, {0x0958, 0x0961}, + {0x0962, 0x0963}, {0x0964, 0x0965}, {0x0966, 0x096F}, + {0x0970, 0x0970}, {0x0971, 0x0971}, {0x0972, 0x097F}, + {0x0980, 0x0980}, {0x0981, 0x0981}, {0x0982, 0x0983}, + {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, + {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, + {0x09BC, 0x09BC}, {0x09BD, 0x09BD}, {0x09BE, 0x09C0}, + {0x09C1, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CC}, + {0x09CD, 0x09CD}, {0x09CE, 0x09CE}, {0x09D7, 0x09D7}, + {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09E2, 0x09E3}, + {0x09E6, 0x09EF}, {0x09F0, 0x09F1}, {0x09F2, 0x09F3}, + {0x09F4, 0x09F9}, {0x09FA, 0x09FA}, {0x09FB, 0x09FB}, + {0x0A01, 0x0A02}, {0x0A03, 0x0A03}, {0x0A05, 0x0A0A}, + {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, + {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A40}, {0x0A41, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A6F}, + {0x0A70, 0x0A71}, {0x0A72, 0x0A74}, {0x0A75, 0x0A75}, + {0x0A81, 0x0A82}, {0x0A83, 0x0A83}, {0x0A85, 0x0A8D}, + {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, + {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0ABC}, + {0x0ABD, 0x0ABD}, {0x0ABE, 0x0AC0}, {0x0AC1, 0x0AC5}, + {0x0AC7, 0x0AC8}, {0x0AC9, 0x0AC9}, {0x0ACB, 0x0ACC}, + {0x0ACD, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE1}, + {0x0AE2, 0x0AE3}, {0x0AE6, 0x0AEF}, {0x0AF0, 0x0AF0}, + {0x0AF1, 0x0AF1}, {0x0AF9, 0x0AF9}, {0x0B01, 0x0B01}, + {0x0B02, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, + {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, + {0x0B35, 0x0B39}, {0x0B3C, 0x0B3C}, {0x0B3D, 0x0B3D}, + {0x0B3E, 0x0B3E}, {0x0B3F, 0x0B3F}, {0x0B40, 0x0B40}, + {0x0B41, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4C}, + {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B57, 0x0B57}, + {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B62, 0x0B63}, + {0x0B66, 0x0B6F}, {0x0B70, 0x0B70}, {0x0B71, 0x0B71}, + {0x0B72, 0x0B77}, {0x0B82, 0x0B82}, {0x0B83, 0x0B83}, + {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, + {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, + {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, + {0x0BBE, 0x0BBF}, {0x0BC0, 0x0BC0}, {0x0BC1, 0x0BC2}, + {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCC}, {0x0BCD, 0x0BCD}, + {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BEF}, + {0x0BF0, 0x0BF2}, {0x0BF3, 0x0BF8}, {0x0BF9, 0x0BF9}, + {0x0BFA, 0x0BFA}, {0x0C00, 0x0C00}, {0x0C01, 0x0C03}, + {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, + {0x0C2A, 0x0C39}, {0x0C3D, 0x0C3D}, {0x0C3E, 0x0C40}, + {0x0C41, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C61}, + {0x0C62, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C78, 0x0C7E}, + {0x0C7F, 0x0C7F}, {0x0C80, 0x0C80}, {0x0C81, 0x0C81}, + {0x0C82, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, + {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, + {0x0CBC, 0x0CBC}, {0x0CBD, 0x0CBD}, {0x0CBE, 0x0CBE}, + {0x0CBF, 0x0CBF}, {0x0CC0, 0x0CC4}, {0x0CC6, 0x0CC6}, + {0x0CC7, 0x0CC8}, {0x0CCA, 0x0CCB}, {0x0CCC, 0x0CCD}, + {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, + {0x0CE2, 0x0CE3}, {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, + {0x0D01, 0x0D01}, {0x0D02, 0x0D03}, {0x0D05, 0x0D0C}, + {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, {0x0D3D, 0x0D3D}, + {0x0D3E, 0x0D40}, {0x0D41, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4C}, {0x0D4D, 0x0D4D}, {0x0D4E, 0x0D4E}, + {0x0D4F, 0x0D4F}, {0x0D54, 0x0D56}, {0x0D57, 0x0D57}, + {0x0D58, 0x0D5E}, {0x0D5F, 0x0D61}, {0x0D62, 0x0D63}, + {0x0D66, 0x0D6F}, {0x0D70, 0x0D78}, {0x0D79, 0x0D79}, + {0x0D7A, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96}, + {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, + {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD1}, + {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, + {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF3}, {0x0DF4, 0x0DF4}, + {0x0E01, 0x0E30}, {0x0E31, 0x0E31}, {0x0E32, 0x0E33}, + {0x0E34, 0x0E3A}, {0x0E3F, 0x0E3F}, {0x0E40, 0x0E45}, + {0x0E46, 0x0E46}, {0x0E47, 0x0E4E}, {0x0E4F, 0x0E4F}, + {0x0E50, 0x0E59}, {0x0E5A, 0x0E5B}, {0x0E81, 0x0E82}, + {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, + {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, + {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, + {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EB0}, {0x0EB1, 0x0EB1}, + {0x0EB2, 0x0EB3}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, + {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, + {0x0F00, 0x0F00}, {0x0F01, 0x0F03}, {0x0F04, 0x0F12}, + {0x0F13, 0x0F13}, {0x0F14, 0x0F14}, {0x0F15, 0x0F17}, + {0x0F18, 0x0F19}, {0x0F1A, 0x0F1F}, {0x0F20, 0x0F29}, + {0x0F2A, 0x0F33}, {0x0F34, 0x0F34}, {0x0F35, 0x0F35}, + {0x0F36, 0x0F36}, {0x0F37, 0x0F37}, {0x0F38, 0x0F38}, + {0x0F39, 0x0F39}, {0x0F3A, 0x0F3A}, {0x0F3B, 0x0F3B}, + {0x0F3C, 0x0F3C}, {0x0F3D, 0x0F3D}, {0x0F3E, 0x0F3F}, + {0x0F40, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F7E}, + {0x0F7F, 0x0F7F}, {0x0F80, 0x0F84}, {0x0F85, 0x0F85}, + {0x0F86, 0x0F87}, {0x0F88, 0x0F8C}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FBE, 0x0FC5}, {0x0FC6, 0x0FC6}, + {0x0FC7, 0x0FCC}, {0x0FCE, 0x0FCF}, {0x0FD0, 0x0FD4}, + {0x0FD5, 0x0FD8}, {0x0FD9, 0x0FDA}, {0x1000, 0x102A}, + {0x102B, 0x102C}, {0x102D, 0x1030}, {0x1031, 0x1031}, + {0x1032, 0x1037}, {0x1038, 0x1038}, {0x1039, 0x103A}, + {0x103B, 0x103C}, {0x103D, 0x103E}, {0x103F, 0x103F}, + {0x1040, 0x1049}, {0x104A, 0x104F}, {0x1050, 0x1055}, + {0x1056, 0x1057}, {0x1058, 0x1059}, {0x105A, 0x105D}, + {0x105E, 0x1060}, {0x1061, 0x1061}, {0x1062, 0x1064}, + {0x1065, 0x1066}, {0x1067, 0x106D}, {0x106E, 0x1070}, + {0x1071, 0x1074}, {0x1075, 0x1081}, {0x1082, 0x1082}, + {0x1083, 0x1084}, {0x1085, 0x1086}, {0x1087, 0x108C}, + {0x108D, 0x108D}, {0x108E, 0x108E}, {0x108F, 0x108F}, + {0x1090, 0x1099}, {0x109A, 0x109C}, {0x109D, 0x109D}, + {0x109E, 0x109F}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, + {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FB, 0x10FB}, + {0x10FC, 0x10FC}, {0x10FD, 0x10FF}, {0x1160, 0x11FF}, + {0x1200, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, + {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, + {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, + {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, + {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, + {0x1318, 0x135A}, {0x135D, 0x135F}, {0x1360, 0x1368}, + {0x1369, 0x137C}, {0x1380, 0x138F}, {0x1390, 0x1399}, + {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x1400}, + {0x1401, 0x166C}, {0x166D, 0x166E}, {0x166F, 0x167F}, + {0x1680, 0x1680}, {0x1681, 0x169A}, {0x169B, 0x169B}, + {0x169C, 0x169C}, {0x16A0, 0x16EA}, {0x16EB, 0x16ED}, + {0x16EE, 0x16F0}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, + {0x170E, 0x1711}, {0x1712, 0x1714}, {0x1720, 0x1731}, + {0x1732, 0x1734}, {0x1735, 0x1736}, {0x1740, 0x1751}, + {0x1752, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, + {0x1772, 0x1773}, {0x1780, 0x17B3}, {0x17B4, 0x17B5}, + {0x17B6, 0x17B6}, {0x17B7, 0x17BD}, {0x17BE, 0x17C5}, + {0x17C6, 0x17C6}, {0x17C7, 0x17C8}, {0x17C9, 0x17D3}, + {0x17D4, 0x17D6}, {0x17D7, 0x17D7}, {0x17D8, 0x17DA}, + {0x17DB, 0x17DB}, {0x17DC, 0x17DC}, {0x17DD, 0x17DD}, + {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x1805}, + {0x1806, 0x1806}, {0x1807, 0x180A}, {0x180B, 0x180D}, + {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1842}, + {0x1843, 0x1843}, {0x1844, 0x1877}, {0x1880, 0x1884}, + {0x1885, 0x1886}, {0x1887, 0x18A8}, {0x18A9, 0x18A9}, + {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, + {0x1920, 0x1922}, {0x1923, 0x1926}, {0x1927, 0x1928}, + {0x1929, 0x192B}, {0x1930, 0x1931}, {0x1932, 0x1932}, + {0x1933, 0x1938}, {0x1939, 0x193B}, {0x1940, 0x1940}, + {0x1944, 0x1945}, {0x1946, 0x194F}, {0x1950, 0x196D}, + {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, + {0x19D0, 0x19D9}, {0x19DA, 0x19DA}, {0x19DE, 0x19DF}, + {0x19E0, 0x19FF}, {0x1A00, 0x1A16}, {0x1A17, 0x1A18}, + {0x1A19, 0x1A1A}, {0x1A1B, 0x1A1B}, {0x1A1E, 0x1A1F}, + {0x1A20, 0x1A54}, {0x1A55, 0x1A55}, {0x1A56, 0x1A56}, + {0x1A57, 0x1A57}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60}, + {0x1A61, 0x1A61}, {0x1A62, 0x1A62}, {0x1A63, 0x1A64}, + {0x1A65, 0x1A6C}, {0x1A6D, 0x1A72}, {0x1A73, 0x1A7C}, + {0x1A7F, 0x1A7F}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, + {0x1AA0, 0x1AA6}, {0x1AA7, 0x1AA7}, {0x1AA8, 0x1AAD}, + {0x1AB0, 0x1ABD}, {0x1ABE, 0x1ABE}, {0x1B00, 0x1B03}, + {0x1B04, 0x1B04}, {0x1B05, 0x1B33}, {0x1B34, 0x1B34}, + {0x1B35, 0x1B35}, {0x1B36, 0x1B3A}, {0x1B3B, 0x1B3B}, + {0x1B3C, 0x1B3C}, {0x1B3D, 0x1B41}, {0x1B42, 0x1B42}, + {0x1B43, 0x1B44}, {0x1B45, 0x1B4B}, {0x1B50, 0x1B59}, + {0x1B5A, 0x1B60}, {0x1B61, 0x1B6A}, {0x1B6B, 0x1B73}, + {0x1B74, 0x1B7C}, {0x1B80, 0x1B81}, {0x1B82, 0x1B82}, + {0x1B83, 0x1BA0}, {0x1BA1, 0x1BA1}, {0x1BA2, 0x1BA5}, + {0x1BA6, 0x1BA7}, {0x1BA8, 0x1BA9}, {0x1BAA, 0x1BAA}, + {0x1BAB, 0x1BAD}, {0x1BAE, 0x1BAF}, {0x1BB0, 0x1BB9}, + {0x1BBA, 0x1BBF}, {0x1BC0, 0x1BE5}, {0x1BE6, 0x1BE6}, + {0x1BE7, 0x1BE7}, {0x1BE8, 0x1BE9}, {0x1BEA, 0x1BEC}, + {0x1BED, 0x1BED}, {0x1BEE, 0x1BEE}, {0x1BEF, 0x1BF1}, + {0x1BF2, 0x1BF3}, {0x1BFC, 0x1BFF}, {0x1C00, 0x1C23}, + {0x1C24, 0x1C2B}, {0x1C2C, 0x1C33}, {0x1C34, 0x1C35}, + {0x1C36, 0x1C37}, {0x1C3B, 0x1C3F}, {0x1C40, 0x1C49}, + {0x1C4D, 0x1C4F}, {0x1C50, 0x1C59}, {0x1C5A, 0x1C77}, + {0x1C78, 0x1C7D}, {0x1C7E, 0x1C7F}, {0x1C80, 0x1C88}, + {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CD2}, {0x1CD3, 0x1CD3}, + {0x1CD4, 0x1CE0}, {0x1CE1, 0x1CE1}, {0x1CE2, 0x1CE8}, + {0x1CE9, 0x1CEC}, {0x1CED, 0x1CED}, {0x1CEE, 0x1CF1}, + {0x1CF2, 0x1CF3}, {0x1CF4, 0x1CF4}, {0x1CF5, 0x1CF6}, + {0x1CF8, 0x1CF9}, {0x1D00, 0x1D2B}, {0x1D2C, 0x1D6A}, + {0x1D6B, 0x1D77}, {0x1D78, 0x1D78}, {0x1D79, 0x1D7F}, + {0x1D80, 0x1D9A}, {0x1D9B, 0x1DBF}, {0x1DC0, 0x1DF5}, + {0x1DFB, 0x1DFF}, {0x1E00, 0x1EFF}, {0x1F00, 0x1F15}, + {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, + {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, + {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, + {0x1FB6, 0x1FBC}, {0x1FBD, 0x1FBD}, {0x1FBE, 0x1FBE}, + {0x1FBF, 0x1FC1}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, + {0x1FCD, 0x1FCF}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, + {0x1FDD, 0x1FDF}, {0x1FE0, 0x1FEC}, {0x1FED, 0x1FEF}, + {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x1FFD, 0x1FFE}, + {0x2000, 0x200A}, {0x200B, 0x200F}, {0x2011, 0x2012}, + {0x2017, 0x2017}, {0x201A, 0x201A}, {0x201B, 0x201B}, + {0x201E, 0x201E}, {0x201F, 0x201F}, {0x2023, 0x2023}, + {0x2028, 0x2028}, {0x2029, 0x2029}, {0x202A, 0x202E}, + {0x202F, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, + {0x2036, 0x2038}, {0x2039, 0x2039}, {0x203A, 0x203A}, + {0x203C, 0x203D}, {0x203F, 0x2040}, {0x2041, 0x2043}, + {0x2044, 0x2044}, {0x2045, 0x2045}, {0x2046, 0x2046}, + {0x2047, 0x2051}, {0x2052, 0x2052}, {0x2053, 0x2053}, + {0x2054, 0x2054}, {0x2055, 0x205E}, {0x205F, 0x205F}, + {0x2060, 0x2064}, {0x2066, 0x206F}, {0x2070, 0x2070}, + {0x2071, 0x2071}, {0x2075, 0x2079}, {0x207A, 0x207C}, + {0x207D, 0x207D}, {0x207E, 0x207E}, {0x2080, 0x2080}, + {0x2085, 0x2089}, {0x208A, 0x208C}, {0x208D, 0x208D}, + {0x208E, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, + {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20DC}, + {0x20DD, 0x20E0}, {0x20E1, 0x20E1}, {0x20E2, 0x20E4}, + {0x20E5, 0x20F0}, {0x2100, 0x2101}, {0x2102, 0x2102}, + {0x2104, 0x2104}, {0x2106, 0x2106}, {0x2107, 0x2107}, + {0x2108, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2114}, + {0x2115, 0x2115}, {0x2117, 0x2117}, {0x2118, 0x2118}, + {0x2119, 0x211D}, {0x211E, 0x2120}, {0x2123, 0x2123}, + {0x2124, 0x2124}, {0x2125, 0x2125}, {0x2127, 0x2127}, + {0x2128, 0x2128}, {0x2129, 0x2129}, {0x212A, 0x212A}, + {0x212C, 0x212D}, {0x212E, 0x212E}, {0x212F, 0x2134}, + {0x2135, 0x2138}, {0x2139, 0x2139}, {0x213A, 0x213B}, + {0x213C, 0x213F}, {0x2140, 0x2144}, {0x2145, 0x2149}, + {0x214A, 0x214A}, {0x214B, 0x214B}, {0x214C, 0x214D}, + {0x214E, 0x214E}, {0x214F, 0x214F}, {0x2150, 0x2152}, + {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, + {0x217A, 0x2182}, {0x2183, 0x2184}, {0x2185, 0x2188}, + {0x218A, 0x218B}, {0x219A, 0x219B}, {0x219C, 0x219F}, + {0x21A0, 0x21A0}, {0x21A1, 0x21A2}, {0x21A3, 0x21A3}, + {0x21A4, 0x21A5}, {0x21A6, 0x21A6}, {0x21A7, 0x21AD}, + {0x21AE, 0x21AE}, {0x21AF, 0x21B7}, {0x21BA, 0x21CD}, + {0x21CE, 0x21CF}, {0x21D0, 0x21D1}, {0x21D3, 0x21D3}, + {0x21D5, 0x21E6}, {0x21E8, 0x21F3}, {0x21F4, 0x21FF}, + {0x2201, 0x2201}, {0x2204, 0x2206}, {0x2209, 0x220A}, + {0x220C, 0x220E}, {0x2210, 0x2210}, {0x2212, 0x2214}, + {0x2216, 0x2219}, {0x221B, 0x221C}, {0x2221, 0x2222}, + {0x2224, 0x2224}, {0x2226, 0x2226}, {0x222D, 0x222D}, + {0x222F, 0x2233}, {0x2238, 0x223B}, {0x223E, 0x2247}, + {0x2249, 0x224B}, {0x224D, 0x2251}, {0x2253, 0x225F}, + {0x2262, 0x2263}, {0x2268, 0x2269}, {0x226C, 0x226D}, + {0x2270, 0x2281}, {0x2284, 0x2285}, {0x2288, 0x2294}, + {0x2296, 0x2298}, {0x229A, 0x22A4}, {0x22A6, 0x22BE}, + {0x22C0, 0x22FF}, {0x2300, 0x2307}, {0x2308, 0x2308}, + {0x2309, 0x2309}, {0x230A, 0x230A}, {0x230B, 0x230B}, + {0x230C, 0x2311}, {0x2313, 0x2319}, {0x231C, 0x231F}, + {0x2320, 0x2321}, {0x2322, 0x2328}, {0x232B, 0x237B}, + {0x237C, 0x237C}, {0x237D, 0x239A}, {0x239B, 0x23B3}, + {0x23B4, 0x23DB}, {0x23DC, 0x23E1}, {0x23E2, 0x23E8}, + {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, + {0x2400, 0x2426}, {0x2440, 0x244A}, {0x24EA, 0x24EA}, + {0x254C, 0x254F}, {0x2574, 0x257F}, {0x2590, 0x2591}, + {0x2596, 0x259F}, {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, + {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, + {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, + {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, {0x25F0, 0x25F7}, + {0x25F8, 0x25FC}, {0x25FF, 0x25FF}, {0x2600, 0x2604}, + {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613}, + {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F}, + {0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F}, + {0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B}, + {0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692}, + {0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9}, + {0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2}, + {0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709}, + {0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B}, + {0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756}, + {0x2758, 0x2767}, {0x2768, 0x2768}, {0x2769, 0x2769}, + {0x276A, 0x276A}, {0x276B, 0x276B}, {0x276C, 0x276C}, + {0x276D, 0x276D}, {0x276E, 0x276E}, {0x276F, 0x276F}, + {0x2770, 0x2770}, {0x2771, 0x2771}, {0x2772, 0x2772}, + {0x2773, 0x2773}, {0x2774, 0x2774}, {0x2775, 0x2775}, + {0x2780, 0x2793}, {0x2794, 0x2794}, {0x2798, 0x27AF}, + {0x27B1, 0x27BE}, {0x27C0, 0x27C4}, {0x27C5, 0x27C5}, + {0x27C6, 0x27C6}, {0x27C7, 0x27E5}, {0x27EE, 0x27EE}, + {0x27EF, 0x27EF}, {0x27F0, 0x27FF}, {0x2800, 0x28FF}, + {0x2900, 0x297F}, {0x2980, 0x2982}, {0x2983, 0x2983}, + {0x2984, 0x2984}, {0x2987, 0x2987}, {0x2988, 0x2988}, + {0x2989, 0x2989}, {0x298A, 0x298A}, {0x298B, 0x298B}, + {0x298C, 0x298C}, {0x298D, 0x298D}, {0x298E, 0x298E}, + {0x298F, 0x298F}, {0x2990, 0x2990}, {0x2991, 0x2991}, + {0x2992, 0x2992}, {0x2993, 0x2993}, {0x2994, 0x2994}, + {0x2995, 0x2995}, {0x2996, 0x2996}, {0x2997, 0x2997}, + {0x2998, 0x2998}, {0x2999, 0x29D7}, {0x29D8, 0x29D8}, + {0x29D9, 0x29D9}, {0x29DA, 0x29DA}, {0x29DB, 0x29DB}, + {0x29DC, 0x29FB}, {0x29FC, 0x29FC}, {0x29FD, 0x29FD}, + {0x29FE, 0x29FF}, {0x2A00, 0x2AFF}, {0x2B00, 0x2B1A}, + {0x2B1D, 0x2B2F}, {0x2B30, 0x2B44}, {0x2B45, 0x2B46}, + {0x2B47, 0x2B4C}, {0x2B4D, 0x2B4F}, {0x2B51, 0x2B54}, + {0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9}, + {0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF}, + {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2C7B}, + {0x2C7C, 0x2C7D}, {0x2C7E, 0x2C7F}, {0x2C80, 0x2CE4}, + {0x2CE5, 0x2CEA}, {0x2CEB, 0x2CEE}, {0x2CEF, 0x2CF1}, + {0x2CF2, 0x2CF3}, {0x2CF9, 0x2CFC}, {0x2CFD, 0x2CFD}, + {0x2CFE, 0x2CFF}, {0x2D00, 0x2D25}, {0x2D27, 0x2D27}, + {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D6F}, + {0x2D70, 0x2D70}, {0x2D7F, 0x2D7F}, {0x2D80, 0x2D96}, + {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, + {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, + {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2DFF}, + {0x2E00, 0x2E01}, {0x2E02, 0x2E02}, {0x2E03, 0x2E03}, + {0x2E04, 0x2E04}, {0x2E05, 0x2E05}, {0x2E06, 0x2E08}, + {0x2E09, 0x2E09}, {0x2E0A, 0x2E0A}, {0x2E0B, 0x2E0B}, + {0x2E0C, 0x2E0C}, {0x2E0D, 0x2E0D}, {0x2E0E, 0x2E16}, + {0x2E17, 0x2E17}, {0x2E18, 0x2E19}, {0x2E1A, 0x2E1A}, + {0x2E1B, 0x2E1B}, {0x2E1C, 0x2E1C}, {0x2E1D, 0x2E1D}, + {0x2E1E, 0x2E1F}, {0x2E20, 0x2E20}, {0x2E21, 0x2E21}, + {0x2E22, 0x2E22}, {0x2E23, 0x2E23}, {0x2E24, 0x2E24}, + {0x2E25, 0x2E25}, {0x2E26, 0x2E26}, {0x2E27, 0x2E27}, + {0x2E28, 0x2E28}, {0x2E29, 0x2E29}, {0x2E2A, 0x2E2E}, + {0x2E2F, 0x2E2F}, {0x2E30, 0x2E39}, {0x2E3A, 0x2E3B}, + {0x2E3C, 0x2E3F}, {0x2E40, 0x2E40}, {0x2E41, 0x2E41}, + {0x2E42, 0x2E42}, {0x2E43, 0x2E44}, {0x303F, 0x303F}, + {0x4DC0, 0x4DFF}, {0xA4D0, 0xA4F7}, {0xA4F8, 0xA4FD}, + {0xA4FE, 0xA4FF}, {0xA500, 0xA60B}, {0xA60C, 0xA60C}, + {0xA60D, 0xA60F}, {0xA610, 0xA61F}, {0xA620, 0xA629}, + {0xA62A, 0xA62B}, {0xA640, 0xA66D}, {0xA66E, 0xA66E}, + {0xA66F, 0xA66F}, {0xA670, 0xA672}, {0xA673, 0xA673}, + {0xA674, 0xA67D}, {0xA67E, 0xA67E}, {0xA67F, 0xA67F}, + {0xA680, 0xA69B}, {0xA69C, 0xA69D}, {0xA69E, 0xA69F}, + {0xA6A0, 0xA6E5}, {0xA6E6, 0xA6EF}, {0xA6F0, 0xA6F1}, + {0xA6F2, 0xA6F7}, {0xA700, 0xA716}, {0xA717, 0xA71F}, + {0xA720, 0xA721}, {0xA722, 0xA76F}, {0xA770, 0xA770}, + {0xA771, 0xA787}, {0xA788, 0xA788}, {0xA789, 0xA78A}, + {0xA78B, 0xA78E}, {0xA78F, 0xA78F}, {0xA790, 0xA7AE}, + {0xA7B0, 0xA7B7}, {0xA7F7, 0xA7F7}, {0xA7F8, 0xA7F9}, + {0xA7FA, 0xA7FA}, {0xA7FB, 0xA7FF}, {0xA800, 0xA801}, + {0xA802, 0xA802}, {0xA803, 0xA805}, {0xA806, 0xA806}, + {0xA807, 0xA80A}, {0xA80B, 0xA80B}, {0xA80C, 0xA822}, + {0xA823, 0xA824}, {0xA825, 0xA826}, {0xA827, 0xA827}, + {0xA828, 0xA82B}, {0xA830, 0xA835}, {0xA836, 0xA837}, + {0xA838, 0xA838}, {0xA839, 0xA839}, {0xA840, 0xA873}, + {0xA874, 0xA877}, {0xA880, 0xA881}, {0xA882, 0xA8B3}, + {0xA8B4, 0xA8C3}, {0xA8C4, 0xA8C5}, {0xA8CE, 0xA8CF}, + {0xA8D0, 0xA8D9}, {0xA8E0, 0xA8F1}, {0xA8F2, 0xA8F7}, + {0xA8F8, 0xA8FA}, {0xA8FB, 0xA8FB}, {0xA8FC, 0xA8FC}, + {0xA8FD, 0xA8FD}, {0xA900, 0xA909}, {0xA90A, 0xA925}, + {0xA926, 0xA92D}, {0xA92E, 0xA92F}, {0xA930, 0xA946}, + {0xA947, 0xA951}, {0xA952, 0xA953}, {0xA95F, 0xA95F}, + {0xA980, 0xA982}, {0xA983, 0xA983}, {0xA984, 0xA9B2}, + {0xA9B3, 0xA9B3}, {0xA9B4, 0xA9B5}, {0xA9B6, 0xA9B9}, + {0xA9BA, 0xA9BB}, {0xA9BC, 0xA9BC}, {0xA9BD, 0xA9C0}, + {0xA9C1, 0xA9CD}, {0xA9CF, 0xA9CF}, {0xA9D0, 0xA9D9}, + {0xA9DE, 0xA9DF}, {0xA9E0, 0xA9E4}, {0xA9E5, 0xA9E5}, + {0xA9E6, 0xA9E6}, {0xA9E7, 0xA9EF}, {0xA9F0, 0xA9F9}, + {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA29, 0xAA2E}, + {0xAA2F, 0xAA30}, {0xAA31, 0xAA32}, {0xAA33, 0xAA34}, + {0xAA35, 0xAA36}, {0xAA40, 0xAA42}, {0xAA43, 0xAA43}, + {0xAA44, 0xAA4B}, {0xAA4C, 0xAA4C}, {0xAA4D, 0xAA4D}, + {0xAA50, 0xAA59}, {0xAA5C, 0xAA5F}, {0xAA60, 0xAA6F}, + {0xAA70, 0xAA70}, {0xAA71, 0xAA76}, {0xAA77, 0xAA79}, + {0xAA7A, 0xAA7A}, {0xAA7B, 0xAA7B}, {0xAA7C, 0xAA7C}, + {0xAA7D, 0xAA7D}, {0xAA7E, 0xAA7F}, {0xAA80, 0xAAAF}, + {0xAAB0, 0xAAB0}, {0xAAB1, 0xAAB1}, {0xAAB2, 0xAAB4}, + {0xAAB5, 0xAAB6}, {0xAAB7, 0xAAB8}, {0xAAB9, 0xAABD}, + {0xAABE, 0xAABF}, {0xAAC0, 0xAAC0}, {0xAAC1, 0xAAC1}, + {0xAAC2, 0xAAC2}, {0xAADB, 0xAADC}, {0xAADD, 0xAADD}, + {0xAADE, 0xAADF}, {0xAAE0, 0xAAEA}, {0xAAEB, 0xAAEB}, + {0xAAEC, 0xAAED}, {0xAAEE, 0xAAEF}, {0xAAF0, 0xAAF1}, + {0xAAF2, 0xAAF2}, {0xAAF3, 0xAAF4}, {0xAAF5, 0xAAF5}, + {0xAAF6, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, + {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, + {0xAB30, 0xAB5A}, {0xAB5B, 0xAB5B}, {0xAB5C, 0xAB5F}, + {0xAB60, 0xAB65}, {0xAB70, 0xABBF}, {0xABC0, 0xABE2}, + {0xABE3, 0xABE4}, {0xABE5, 0xABE5}, {0xABE6, 0xABE7}, + {0xABE8, 0xABE8}, {0xABE9, 0xABEA}, {0xABEB, 0xABEB}, + {0xABEC, 0xABEC}, {0xABED, 0xABED}, {0xABF0, 0xABF9}, + {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDB7F}, + {0xDB80, 0xDBFF}, {0xDC00, 0xDFFF}, {0xFB00, 0xFB06}, + {0xFB13, 0xFB17}, {0xFB1D, 0xFB1D}, {0xFB1E, 0xFB1E}, + {0xFB1F, 0xFB28}, {0xFB29, 0xFB29}, {0xFB2A, 0xFB36}, + {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, + {0xFB43, 0xFB44}, {0xFB46, 0xFB4F}, {0xFB50, 0xFBB1}, + {0xFBB2, 0xFBC1}, {0xFBD3, 0xFD3D}, {0xFD3E, 0xFD3E}, + {0xFD3F, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, + {0xFDF0, 0xFDFB}, {0xFDFC, 0xFDFC}, {0xFDFD, 0xFDFD}, + {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFC, 0xFFFC}, + {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, + {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D}, + {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133}, + {0x10137, 0x1013F}, {0x10140, 0x10174}, {0x10175, 0x10178}, + {0x10179, 0x10189}, {0x1018A, 0x1018B}, {0x1018C, 0x1018E}, + {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, + {0x101FD, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0}, + {0x102E0, 0x102E0}, {0x102E1, 0x102FB}, {0x10300, 0x1031F}, + {0x10320, 0x10323}, {0x10330, 0x10340}, {0x10341, 0x10341}, + {0x10342, 0x10349}, {0x1034A, 0x1034A}, {0x10350, 0x10375}, + {0x10376, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x1039F}, + {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x103D0, 0x103D0}, + {0x103D1, 0x103D5}, {0x10400, 0x1044F}, {0x10450, 0x1047F}, + {0x10480, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, + {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, + {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, + {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, + {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, + {0x1083F, 0x1083F}, {0x10840, 0x10855}, {0x10857, 0x10857}, + {0x10858, 0x1085F}, {0x10860, 0x10876}, {0x10877, 0x10878}, + {0x10879, 0x1087F}, {0x10880, 0x1089E}, {0x108A7, 0x108AF}, + {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x108FF}, + {0x10900, 0x10915}, {0x10916, 0x1091B}, {0x1091F, 0x1091F}, + {0x10920, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x1099F}, + {0x109A0, 0x109B7}, {0x109BC, 0x109BD}, {0x109BE, 0x109BF}, + {0x109C0, 0x109CF}, {0x109D2, 0x109FF}, {0x10A00, 0x10A00}, + {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, + {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10A40, 0x10A47}, + {0x10A50, 0x10A58}, {0x10A60, 0x10A7C}, {0x10A7D, 0x10A7E}, + {0x10A7F, 0x10A7F}, {0x10A80, 0x10A9C}, {0x10A9D, 0x10A9F}, + {0x10AC0, 0x10AC7}, {0x10AC8, 0x10AC8}, {0x10AC9, 0x10AE4}, + {0x10AE5, 0x10AE6}, {0x10AEB, 0x10AEF}, {0x10AF0, 0x10AF6}, + {0x10B00, 0x10B35}, {0x10B39, 0x10B3F}, {0x10B40, 0x10B55}, + {0x10B58, 0x10B5F}, {0x10B60, 0x10B72}, {0x10B78, 0x10B7F}, + {0x10B80, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, + {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, + {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x11000}, + {0x11001, 0x11001}, {0x11002, 0x11002}, {0x11003, 0x11037}, + {0x11038, 0x11046}, {0x11047, 0x1104D}, {0x11052, 0x11065}, + {0x11066, 0x1106F}, {0x1107F, 0x1107F}, {0x11080, 0x11081}, + {0x11082, 0x11082}, {0x11083, 0x110AF}, {0x110B0, 0x110B2}, + {0x110B3, 0x110B6}, {0x110B7, 0x110B8}, {0x110B9, 0x110BA}, + {0x110BB, 0x110BC}, {0x110BD, 0x110BD}, {0x110BE, 0x110C1}, + {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11102}, + {0x11103, 0x11126}, {0x11127, 0x1112B}, {0x1112C, 0x1112C}, + {0x1112D, 0x11134}, {0x11136, 0x1113F}, {0x11140, 0x11143}, + {0x11150, 0x11172}, {0x11173, 0x11173}, {0x11174, 0x11175}, + {0x11176, 0x11176}, {0x11180, 0x11181}, {0x11182, 0x11182}, + {0x11183, 0x111B2}, {0x111B3, 0x111B5}, {0x111B6, 0x111BE}, + {0x111BF, 0x111C0}, {0x111C1, 0x111C4}, {0x111C5, 0x111C9}, + {0x111CA, 0x111CC}, {0x111CD, 0x111CD}, {0x111D0, 0x111D9}, + {0x111DA, 0x111DA}, {0x111DB, 0x111DB}, {0x111DC, 0x111DC}, + {0x111DD, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, + {0x11213, 0x1122B}, {0x1122C, 0x1122E}, {0x1122F, 0x11231}, + {0x11232, 0x11233}, {0x11234, 0x11234}, {0x11235, 0x11235}, + {0x11236, 0x11237}, {0x11238, 0x1123D}, {0x1123E, 0x1123E}, + {0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D}, + {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112A9, 0x112A9}, + {0x112B0, 0x112DE}, {0x112DF, 0x112DF}, {0x112E0, 0x112E2}, + {0x112E3, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11301}, + {0x11302, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, + {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, + {0x11335, 0x11339}, {0x1133C, 0x1133C}, {0x1133D, 0x1133D}, + {0x1133E, 0x1133F}, {0x11340, 0x11340}, {0x11341, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350}, + {0x11357, 0x11357}, {0x1135D, 0x11361}, {0x11362, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x11434}, + {0x11435, 0x11437}, {0x11438, 0x1143F}, {0x11440, 0x11441}, + {0x11442, 0x11444}, {0x11445, 0x11445}, {0x11446, 0x11446}, + {0x11447, 0x1144A}, {0x1144B, 0x1144F}, {0x11450, 0x11459}, + {0x1145B, 0x1145B}, {0x1145D, 0x1145D}, {0x11480, 0x114AF}, + {0x114B0, 0x114B2}, {0x114B3, 0x114B8}, {0x114B9, 0x114B9}, + {0x114BA, 0x114BA}, {0x114BB, 0x114BE}, {0x114BF, 0x114C0}, + {0x114C1, 0x114C1}, {0x114C2, 0x114C3}, {0x114C4, 0x114C5}, + {0x114C6, 0x114C6}, {0x114C7, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115AE}, {0x115AF, 0x115B1}, {0x115B2, 0x115B5}, + {0x115B8, 0x115BB}, {0x115BC, 0x115BD}, {0x115BE, 0x115BE}, + {0x115BF, 0x115C0}, {0x115C1, 0x115D7}, {0x115D8, 0x115DB}, + {0x115DC, 0x115DD}, {0x11600, 0x1162F}, {0x11630, 0x11632}, + {0x11633, 0x1163A}, {0x1163B, 0x1163C}, {0x1163D, 0x1163D}, + {0x1163E, 0x1163E}, {0x1163F, 0x11640}, {0x11641, 0x11643}, + {0x11644, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, + {0x11680, 0x116AA}, {0x116AB, 0x116AB}, {0x116AC, 0x116AC}, + {0x116AD, 0x116AD}, {0x116AE, 0x116AF}, {0x116B0, 0x116B5}, + {0x116B6, 0x116B6}, {0x116B7, 0x116B7}, {0x116C0, 0x116C9}, + {0x11700, 0x11719}, {0x1171D, 0x1171F}, {0x11720, 0x11721}, + {0x11722, 0x11725}, {0x11726, 0x11726}, {0x11727, 0x1172B}, + {0x11730, 0x11739}, {0x1173A, 0x1173B}, {0x1173C, 0x1173E}, + {0x1173F, 0x1173F}, {0x118A0, 0x118DF}, {0x118E0, 0x118E9}, + {0x118EA, 0x118F2}, {0x118FF, 0x118FF}, {0x11AC0, 0x11AF8}, + {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C2F, 0x11C2F}, + {0x11C30, 0x11C36}, {0x11C38, 0x11C3D}, {0x11C3E, 0x11C3E}, + {0x11C3F, 0x11C3F}, {0x11C40, 0x11C40}, {0x11C41, 0x11C45}, + {0x11C50, 0x11C59}, {0x11C5A, 0x11C6C}, {0x11C70, 0x11C71}, + {0x11C72, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CA9}, + {0x11CAA, 0x11CB0}, {0x11CB1, 0x11CB1}, {0x11CB2, 0x11CB3}, + {0x11CB4, 0x11CB4}, {0x11CB5, 0x11CB6}, {0x12000, 0x12399}, + {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, + {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, + {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F}, + {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF4}, {0x16AF5, 0x16AF5}, + {0x16B00, 0x16B2F}, {0x16B30, 0x16B36}, {0x16B37, 0x16B3B}, + {0x16B3C, 0x16B3F}, {0x16B40, 0x16B43}, {0x16B44, 0x16B44}, + {0x16B45, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, + {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, + {0x16F50, 0x16F50}, {0x16F51, 0x16F7E}, {0x16F8F, 0x16F92}, + {0x16F93, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9C}, + {0x1BC9D, 0x1BC9E}, {0x1BC9F, 0x1BC9F}, {0x1BCA0, 0x1BCA3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, + {0x1D165, 0x1D166}, {0x1D167, 0x1D169}, {0x1D16A, 0x1D16C}, + {0x1D16D, 0x1D172}, {0x1D173, 0x1D17A}, {0x1D17B, 0x1D182}, + {0x1D183, 0x1D184}, {0x1D185, 0x1D18B}, {0x1D18C, 0x1D1A9}, + {0x1D1AA, 0x1D1AD}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, + {0x1D242, 0x1D244}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, + {0x1D360, 0x1D371}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, + {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, + {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, + {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, + {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, + {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, + {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, + {0x1D6C1, 0x1D6C1}, {0x1D6C2, 0x1D6DA}, {0x1D6DB, 0x1D6DB}, + {0x1D6DC, 0x1D6FA}, {0x1D6FB, 0x1D6FB}, {0x1D6FC, 0x1D714}, + {0x1D715, 0x1D715}, {0x1D716, 0x1D734}, {0x1D735, 0x1D735}, + {0x1D736, 0x1D74E}, {0x1D74F, 0x1D74F}, {0x1D750, 0x1D76E}, + {0x1D76F, 0x1D76F}, {0x1D770, 0x1D788}, {0x1D789, 0x1D789}, + {0x1D78A, 0x1D7A8}, {0x1D7A9, 0x1D7A9}, {0x1D7AA, 0x1D7C2}, + {0x1D7C3, 0x1D7C3}, {0x1D7C4, 0x1D7CB}, {0x1D7CE, 0x1D7FF}, + {0x1D800, 0x1D9FF}, {0x1DA00, 0x1DA36}, {0x1DA37, 0x1DA3A}, + {0x1DA3B, 0x1DA6C}, {0x1DA6D, 0x1DA74}, {0x1DA75, 0x1DA75}, + {0x1DA76, 0x1DA83}, {0x1DA84, 0x1DA84}, {0x1DA85, 0x1DA86}, + {0x1DA87, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, + {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, + {0x1E8C7, 0x1E8CF}, {0x1E8D0, 0x1E8D6}, {0x1E900, 0x1E943}, + {0x1E944, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, + {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, + {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, + {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, + {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, + {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, + {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, + {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, + {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, + {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, + {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, + {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, + {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, + {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, + {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, + {0x1F12E, 0x1F12E}, {0x1F16A, 0x1F16B}, {0x1F1E6, 0x1F1FF}, + {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, + {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, + {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, + {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, + {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, + {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, + {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6E0, 0x1F6EA}, + {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D4}, + {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, + {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0xE0001, 0xE0001}, + {0xE0020, 0xE007F}, +} + +// Condition have flag EastAsianWidth whether the current locale is CJK or not. +type Condition struct { + EastAsianWidth bool +} + +// NewCondition return new instance of Condition which is current locale. +func NewCondition() *Condition { + return &Condition{EastAsianWidth} +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func (c *Condition) RuneWidth(r rune) int { + switch { + case r < 0 || r > 0x10FFFF || + inTables(r, nonprint, combining, notassigned): + return 0 + case (c.EastAsianWidth && IsAmbiguousWidth(r)) || + inTables(r, doublewidth, emoji): + return 2 + default: + return 1 + } +} + +// StringWidth return width as you can see +func (c *Condition) StringWidth(s string) (width int) { + for _, r := range []rune(s) { + width += c.RuneWidth(r) + } + return width +} + +// Truncate return string truncated with w cells +func (c *Condition) Truncate(s string, w int, tail string) string { + if c.StringWidth(s) <= w { + return s + } + r := []rune(s) + tw := c.StringWidth(tail) + w -= tw + width := 0 + i := 0 + for ; i < len(r); i++ { + cw := c.RuneWidth(r[i]) + if width+cw > w { + break + } + width += cw + } + return string(r[0:i]) + tail +} + +// Wrap return string wrapped with w cells +func (c *Condition) Wrap(s string, w int) string { + width := 0 + out := "" + for _, r := range []rune(s) { + cw := RuneWidth(r) + if r == '\n' { + out += string(r) + width = 0 + continue + } else if width+cw > w { + out += "\n" + width = 0 + out += string(r) + width += cw + continue + } + out += string(r) + width += cw + } + return out +} + +// FillLeft return string filled in left by spaces in w cells +func (c *Condition) FillLeft(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return string(b) + s + } + return s +} + +// FillRight return string filled in left by spaces in w cells +func (c *Condition) FillRight(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return s + string(b) + } + return s +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func RuneWidth(r rune) int { + return DefaultCondition.RuneWidth(r) +} + +// IsAmbiguousWidth returns whether is ambiguous width or not. +func IsAmbiguousWidth(r rune) bool { + return inTables(r, private, ambiguous) +} + +// IsNeutralWidth returns whether is neutral width or not. +func IsNeutralWidth(r rune) bool { + return inTable(r, neutral) +} + +// StringWidth return width as you can see +func StringWidth(s string) (width int) { + return DefaultCondition.StringWidth(s) +} + +// Truncate return string truncated with w cells +func Truncate(s string, w int, tail string) string { + return DefaultCondition.Truncate(s, w, tail) +} + +// Wrap return string wrapped with w cells +func Wrap(s string, w int) string { + return DefaultCondition.Wrap(s, w) +} + +// FillLeft return string filled in left by spaces in w cells +func FillLeft(s string, w int) string { + return DefaultCondition.FillLeft(s, w) +} + +// FillRight return string filled in left by spaces in w cells +func FillRight(s string, w int) string { + return DefaultCondition.FillRight(s, w) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go new file mode 100644 index 000000000..0ce32c5e7 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -0,0 +1,8 @@ +// +build js + +package runewidth + +func IsEastAsian() bool { + // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. + return false +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go new file mode 100644 index 000000000..c579e9a31 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -0,0 +1,77 @@ +// +build !windows,!js + +package runewidth + +import ( + "os" + "regexp" + "strings" +) + +var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) + +var mblenTable = map[string]int{ + "utf-8": 6, + "utf8": 6, + "jis": 8, + "eucjp": 3, + "euckr": 2, + "euccn": 2, + "sjis": 2, + "cp932": 2, + "cp51932": 2, + "cp936": 2, + "cp949": 2, + "cp950": 2, + "big5": 2, + "gbk": 2, + "gb2312": 2, +} + +func isEastAsian(locale string) bool { + charset := strings.ToLower(locale) + r := reLoc.FindStringSubmatch(locale) + if len(r) == 2 { + charset = strings.ToLower(r[1]) + } + + if strings.HasSuffix(charset, "@cjk_narrow") { + return false + } + + for pos, b := range []byte(charset) { + if b == '@' { + charset = charset[:pos] + break + } + } + max := 1 + if m, ok := mblenTable[charset]; ok { + max = m + } + if max > 1 && (charset[0] != 'u' || + strings.HasPrefix(locale, "ja") || + strings.HasPrefix(locale, "ko") || + strings.HasPrefix(locale, "zh")) { + return true + } + return false +} + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + locale := os.Getenv("LC_CTYPE") + if locale == "" { + locale = os.Getenv("LANG") + } + + // ignore C locale + if locale == "POSIX" || locale == "C" { + return false + } + if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { + return false + } + + return isEastAsian(locale) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go new file mode 100644 index 000000000..0258876b9 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -0,0 +1,25 @@ +package runewidth + +import ( + "syscall" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32") + procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") +) + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + r1, _, _ := procGetConsoleOutputCP.Call() + if r1 == 0 { + return false + } + + switch int(r1) { + case 932, 51932, 936, 949, 950: + return true + } + + return false +} diff --git a/vendor/github.com/minio/sha256-simd/.travis.yml b/vendor/github.com/minio/sha256-simd/.travis.yml index 744e64cfd..4f85db539 100644 --- a/vendor/github.com/minio/sha256-simd/.travis.yml +++ b/vendor/github.com/minio/sha256-simd/.travis.yml @@ -7,7 +7,7 @@ os: go: - tip -- 1.11.x +- 1.12.x env: - ARCH=x86_64 @@ -21,4 +21,5 @@ matrix: script: - diff -au <(gofmt -d .) <(printf "") - go test -race -v ./... -- go tool vet -asmdecl . +- go vet -asmdecl . +- ./test-architectures.sh diff --git a/vendor/github.com/minio/sha256-simd/cpuid_other.go b/vendor/github.com/minio/sha256-simd/cpuid_other.go index 04f26ce88..3e4415828 100644 --- a/vendor/github.com/minio/sha256-simd/cpuid_other.go +++ b/vendor/github.com/minio/sha256-simd/cpuid_other.go @@ -13,7 +13,7 @@ // limitations under the License. // -// +build ppc64 ppc64le mips mipsle mips64 mips64le s390x wasm +// +build !386,!amd64,!arm,!arm64 arm64,!linux package sha256 diff --git a/vendor/github.com/minio/sha256-simd/go.mod b/vendor/github.com/minio/sha256-simd/go.mod index b68fb0a05..4451e9eb2 100644 --- a/vendor/github.com/minio/sha256-simd/go.mod +++ b/vendor/github.com/minio/sha256-simd/go.mod @@ -1 +1,3 @@ module github.com/minio/sha256-simd + +go 1.12 diff --git a/vendor/github.com/minio/sha256-simd/sha256blockAvx2_amd64.go b/vendor/github.com/minio/sha256-simd/sha256blockAvx2_amd64.go index 43ee7a948..52fcaee6d 100644 --- a/vendor/github.com/minio/sha256-simd/sha256blockAvx2_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256blockAvx2_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/sha256blockAvx512_amd64.go b/vendor/github.com/minio/sha256-simd/sha256blockAvx512_amd64.go index e6bd455df..db8e48d31 100644 --- a/vendor/github.com/minio/sha256-simd/sha256blockAvx512_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256blockAvx512_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2017 Minio, Inc. @@ -104,15 +104,16 @@ func (d *Avx512Digest) Sum(in []byte) (result []byte) { } trail := make([]byte, 0, 128) + trail = append(trail, d.x[:d.nx]...) len := d.len // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. var tmp [64]byte tmp[0] = 0x80 if len%64 < 56 { - trail = append(d.x[:d.nx], tmp[0:56-len%64]...) + trail = append(trail, tmp[0:56-len%64]...) } else { - trail = append(d.x[:d.nx], tmp[0:64+56-len%64]...) + trail = append(trail, tmp[0:64+56-len%64]...) } d.nx = 0 @@ -375,7 +376,7 @@ func (a512srv *Avx512Server) reset(uid uint64) { } // Invoke assembly and send results back -func (a512srv *Avx512Server) blocks() (err error) { +func (a512srv *Avx512Server) blocks() { inputs := [16][]byte{} for i := range inputs { @@ -397,7 +398,6 @@ func (a512srv *Avx512Server) blocks() (err error) { delete(a512srv.digests, uid) // Delete entry from hashmap } } - return } func (a512srv *Avx512Server) Write(uid uint64, p []byte) (nn int, err error) { diff --git a/vendor/github.com/minio/sha256-simd/sha256blockAvx_amd64.go b/vendor/github.com/minio/sha256-simd/sha256blockAvx_amd64.go index eb8a0ff0c..c2f71181f 100644 --- a/vendor/github.com/minio/sha256-simd/sha256blockAvx_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256blockAvx_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/sha256blockSha_amd64.go b/vendor/github.com/minio/sha256-simd/sha256blockSha_amd64.go index 383189c8c..483689ef0 100644 --- a/vendor/github.com/minio/sha256-simd/sha256blockSha_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256blockSha_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine package sha256 diff --git a/vendor/github.com/minio/sha256-simd/sha256blockSsse_amd64.go b/vendor/github.com/minio/sha256-simd/sha256blockSsse_amd64.go index 54abbb0f0..1ae2320bd 100644 --- a/vendor/github.com/minio/sha256-simd/sha256blockSsse_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256blockSsse_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/sha256block_386.go b/vendor/github.com/minio/sha256-simd/sha256block_386.go deleted file mode 100644 index a4153b918..000000000 --- a/vendor/github.com/minio/sha256-simd/sha256block_386.go +++ /dev/null @@ -1,25 +0,0 @@ -//+build !noasm - -/* - * Minio Cloud Storage, (C) 2016 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sha256 - -func blockArmGo(dig *digest, p []byte) {} -func blockAvx2Go(dig *digest, p []byte) {} -func blockAvxGo(dig *digest, p []byte) {} -func blockSsseGo(dig *digest, p []byte) {} -func blockShaGo(dig *digest, p []byte) {} diff --git a/vendor/github.com/minio/sha256-simd/sha256block_amd64.go b/vendor/github.com/minio/sha256-simd/sha256block_amd64.go index 8d341fcfc..1c4d97f0c 100644 --- a/vendor/github.com/minio/sha256-simd/sha256block_amd64.go +++ b/vendor/github.com/minio/sha256-simd/sha256block_amd64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/sha256block_arm.go b/vendor/github.com/minio/sha256-simd/sha256block_arm.go deleted file mode 100644 index 1191c0863..000000000 --- a/vendor/github.com/minio/sha256-simd/sha256block_arm.go +++ /dev/null @@ -1,25 +0,0 @@ -//+build !noasm - -/* - * Minio Cloud Storage, (C) 2016 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sha256 - -func blockAvx2Go(dig *digest, p []byte) {} -func blockAvxGo(dig *digest, p []byte) {} -func blockSsseGo(dig *digest, p []byte) {} -func blockShaGo(dig *digest, p []byte) {} -func blockArmGo(dig *digest, p []byte) {} diff --git a/vendor/github.com/minio/sha256-simd/sha256block_arm64.go b/vendor/github.com/minio/sha256-simd/sha256block_arm64.go index 4441b0c23..0979c20ae 100644 --- a/vendor/github.com/minio/sha256-simd/sha256block_arm64.go +++ b/vendor/github.com/minio/sha256-simd/sha256block_arm64.go @@ -1,4 +1,4 @@ -//+build !noasm +//+build !noasm,!appengine /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/sha256block_arm64.s b/vendor/github.com/minio/sha256-simd/sha256block_arm64.s index db816ac6b..c6ddb3717 100644 --- a/vendor/github.com/minio/sha256-simd/sha256block_arm64.s +++ b/vendor/github.com/minio/sha256-simd/sha256block_arm64.s @@ -1,4 +1,4 @@ -//+build !noasm !appengine +//+build !noasm,!appengine // ARM64 version of SHA256 @@ -28,7 +28,7 @@ TEXT ·blockArm(SB), 7, $0 MOVD h+0(FP), R0 MOVD message+24(FP), R1 - MOVD lenmessage+32(FP), R2 // length of message + MOVD message_len+32(FP), R2 // length of message SUBS $64, R2 BMI complete diff --git a/vendor/github.com/minio/sha256-simd/sha256block_other.go b/vendor/github.com/minio/sha256-simd/sha256block_other.go index 0930d2a2c..0187c950a 100644 --- a/vendor/github.com/minio/sha256-simd/sha256block_other.go +++ b/vendor/github.com/minio/sha256-simd/sha256block_other.go @@ -1,4 +1,4 @@ -//+build noasm appengine ppc64 ppc64le mips mipsle mips64 mips64le s390x wasm +//+build appengine noasm !amd64,!arm64 /* * Minio Cloud Storage, (C) 2019 Minio, Inc. diff --git a/vendor/github.com/minio/sha256-simd/test-architectures.sh b/vendor/github.com/minio/sha256-simd/test-architectures.sh new file mode 100644 index 000000000..50150eaab --- /dev/null +++ b/vendor/github.com/minio/sha256-simd/test-architectures.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +go tool dist list | while IFS=/ read os arch; do + echo "Checking $os/$arch..." + echo " normal" + GOARCH=$arch GOOS=$os go build -o /dev/null ./... + echo " noasm" + GOARCH=$arch GOOS=$os go build -tags noasm -o /dev/null ./... + echo " appengine" + GOARCH=$arch GOOS=$os go build -tags appengine -o /dev/null ./... + echo " noasm,appengine" + GOARCH=$arch GOOS=$os go build -tags 'appengine noasm' -o /dev/null ./... +done diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml b/vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml index 18f4287d7..336deb460 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml +++ b/vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml @@ -4,13 +4,12 @@ os: language: go go: - - 1.11.x + - 1.12.x env: global: - GOTFLAGS="-race" matrix: - - BUILD_DEPTYPE=gx - BUILD_DEPTYPE=gomod @@ -24,7 +23,6 @@ script: cache: directories: - - $GOPATH/src/gx - $GOPATH/pkg/mod - /home/travis/.cache/go-build diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/README.md b/vendor/github.com/multiformats/go-multiaddr-dns/README.md index a1ac5447e..3958c3cf2 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/README.md +++ b/vendor/github.com/multiformats/go-multiaddr-dns/README.md @@ -51,7 +51,7 @@ info: changing query to /dnsaddr/example.net/ipfs/Qmfoo /ip6/2001:db8::a3/tcp/443/wss/ipfs/Qmfoo /ip6/2001:db8::a4/tcp/443/wss/ipfs/Qmbar -# TOOD -c filters by CIDR +# TODO -c filters by CIDR > madns -c /ip4/104.236.76.0/ipcidr/24 /dnsaddr/example.net /ip4/192.0.2.2/tcp/443/wss/ipfs/Qmbar ``` diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/dns.go b/vendor/github.com/multiformats/go-multiaddr-dns/dns.go index 53c82dfd3..6b8ccd04e 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/dns.go +++ b/vendor/github.com/multiformats/go-multiaddr-dns/dns.go @@ -1,69 +1,24 @@ package madns import ( - "bytes" - "fmt" - ma "github.com/multiformats/go-multiaddr" ) // Extracted from source of truth for multicodec codes: https://github.com/multiformats/multicodec const ( - P_DNS4 = 0x0036 - P_DNS6 = 0x0037 - P_DNSADDR = 0x0038 + // Deprecated: use ma.P_DNS4 + P_DNS4 = ma.P_DNS4 + // Deprecated: use ma.P_DNS6 + P_DNS6 = ma.P_DNS6 + // Deprecated: use ma.P_DNSADDR + P_DNSADDR = ma.P_DNSADDR ) -var Dns4Protocol = ma.Protocol{ - Code: P_DNS4, - Size: ma.LengthPrefixedVarSize, - Name: "dns4", - VCode: ma.CodeToVarint(P_DNS4), - Transcoder: DnsTranscoder, -} -var Dns6Protocol = ma.Protocol{ - Code: P_DNS6, - Size: ma.LengthPrefixedVarSize, - Name: "dns6", - VCode: ma.CodeToVarint(P_DNS6), - Transcoder: DnsTranscoder, -} -var DnsaddrProtocol = ma.Protocol{ - Code: P_DNSADDR, - Size: ma.LengthPrefixedVarSize, - Name: "dnsaddr", - VCode: ma.CodeToVarint(P_DNSADDR), - Transcoder: DnsTranscoder, -} +// Deprecated: use ma.ProtocolWithCode(P_DNS4) +var Dns4Protocol = ma.ProtocolWithCode(P_DNS4) -func init() { - err := ma.AddProtocol(Dns4Protocol) - if err != nil { - panic(fmt.Errorf("error registering dns4 protocol: %s", err)) - } - err = ma.AddProtocol(Dns6Protocol) - if err != nil { - panic(fmt.Errorf("error registering dns6 protocol: %s", err)) - } - err = ma.AddProtocol(DnsaddrProtocol) - if err != nil { - panic(fmt.Errorf("error registering dnsaddr protocol: %s", err)) - } -} +// Deprecated: use ma.ProtocolWithCode(P_DNS6) +var Dns6Protocol = ma.ProtocolWithCode(P_DNS6) -var DnsTranscoder = ma.NewTranscoderFromFunctions(dnsStB, dnsBtS, dnsVal) - -func dnsVal(b []byte) error { - if bytes.IndexByte(b, '/') >= 0 { - return fmt.Errorf("domain name %q contains a slash", string(b)) - } - return nil -} - -func dnsStB(s string) ([]byte, error) { - return []byte(s), nil -} - -func dnsBtS(b []byte) (string, error) { - return string(b), nil -} +// Deprecated: use ma.ProtocolWithCode(P_DNSADDR) +var DnsaddrProtocol = ma.ProtocolWithCode(P_DNSADDR) diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/go.mod b/vendor/github.com/multiformats/go-multiaddr-dns/go.mod index fb228c603..c1d394ac4 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/go.mod +++ b/vendor/github.com/multiformats/go-multiaddr-dns/go.mod @@ -1,3 +1,5 @@ module github.com/multiformats/go-multiaddr-dns -require github.com/multiformats/go-multiaddr v0.0.1 +require github.com/multiformats/go-multiaddr v0.1.0 + +go 1.12 diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/go.sum b/vendor/github.com/multiformats/go-multiaddr-dns/go.sum index cbf49eb4e..87f7a0940 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/go.sum +++ b/vendor/github.com/multiformats/go-multiaddr-dns/go.sum @@ -8,8 +8,8 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XC github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0 h1:fkISCUNDb3xIpCcI6BGlPsQE+ywcxzimOsUnHWnrE74= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/package.json b/vendor/github.com/multiformats/go-multiaddr-dns/package.json deleted file mode 100644 index 81fb932c8..000000000 --- a/vendor/github.com/multiformats/go-multiaddr-dns/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "author": "lgierth", - "bugs": { - "url": "https://github.com/multiformats/go-multiaddr-dns/issues" - }, - "gx": { - "dvcsimport": "github.com/multiformats/go-multiaddr-dns" - }, - "gxDependencies": [ - { - "author": "multiformats", - "hash": "QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL", - "name": "go-multiaddr", - "version": "1.4.1" - } - ], - "gxVersion": "0.10.0", - "language": "go", - "license": "MIT", - "name": "go-multiaddr-dns", - "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "0.3.2" -} - diff --git a/vendor/github.com/multiformats/go-multiaddr-dns/resolve.go b/vendor/github.com/multiformats/go-multiaddr-dns/resolve.go index 9c81c2f53..6808ca134 100644 --- a/vendor/github.com/multiformats/go-multiaddr-dns/resolve.go +++ b/vendor/github.com/multiformats/go-multiaddr-dns/resolve.go @@ -174,6 +174,9 @@ func (r *Resolver) resolveDnsaddr(ctx context.Context, maddr ma.Multiaddr) ([]ma // XXX probably insecure func matchDnsaddr(maddr ma.Multiaddr, trailer []ma.Multiaddr) bool { parts := ma.Split(maddr) + if len(trailer) > len(parts) { + return false + } if ma.Join(parts[len(parts)-len(trailer):]...).Equal(ma.Join(trailer...)) { return true } diff --git a/vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml b/vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml index e4b634737..ea3900d91 100644 --- a/vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml +++ b/vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml @@ -4,14 +4,13 @@ os: language: go go: - - 1.11.x + - 1.12.x env: global: - GOTFLAGS="-race" - IPFS_REUSEPORT=false matrix: - - BUILD_DEPTYPE=gx - BUILD_DEPTYPE=gomod @@ -25,7 +24,6 @@ script: cache: directories: - - $GOPATH/src/gx - $GOPATH/pkg/mod - /home/travis/.cache/go-build diff --git a/vendor/github.com/multiformats/go-multiaddr-fmt/go.mod b/vendor/github.com/multiformats/go-multiaddr-fmt/go.mod index db40536c2..f2c79fe86 100644 --- a/vendor/github.com/multiformats/go-multiaddr-fmt/go.mod +++ b/vendor/github.com/multiformats/go-multiaddr-fmt/go.mod @@ -1,6 +1,5 @@ module github.com/multiformats/go-multiaddr-fmt -require ( - github.com/multiformats/go-multiaddr v0.0.1 - github.com/multiformats/go-multiaddr-dns v0.0.2 -) +require github.com/multiformats/go-multiaddr v0.1.1 + +go 1.13 diff --git a/vendor/github.com/multiformats/go-multiaddr-fmt/go.sum b/vendor/github.com/multiformats/go-multiaddr-fmt/go.sum index e6220da65..0061b94a7 100644 --- a/vendor/github.com/multiformats/go-multiaddr-fmt/go.sum +++ b/vendor/github.com/multiformats/go-multiaddr-fmt/go.sum @@ -1,20 +1,20 @@ -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= -github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/multiformats/go-multiaddr-fmt/package.json b/vendor/github.com/multiformats/go-multiaddr-fmt/package.json deleted file mode 100644 index 8303f9c81..000000000 --- a/vendor/github.com/multiformats/go-multiaddr-fmt/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "author": "whyrusleeping", - "bugs": {}, - "gx": { - "dvcsimport": "github.com/multiformats/go-multiaddr-fmt" - }, - "gxDependencies": [ - { - "author": "whyrusleeping", - "hash": "QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL", - "name": "go-multiaddr", - "version": "1.4.1" - }, - { - "author": "lgierth", - "hash": "QmR1T4gAM6XCHQugKnPZgZVPzo8WkuvSpL57EKQFgFbwfd", - "name": "go-multiaddr-dns", - "version": "0.3.2" - } - ], - "gxVersion": "0.6.0", - "gx_version": "0.4.0", - "issues_url": "https://github.com/multiformats/go-multiaddr-fmt", - "language": "go", - "license": "", - "name": "go-multiaddr-fmt", - "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "1.2.11" -} - diff --git a/vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go b/vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go index 62c45414a..4fd6f6a9d 100644 --- a/vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go +++ b/vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go @@ -4,18 +4,18 @@ import ( "strings" ma "github.com/multiformats/go-multiaddr" - madns "github.com/multiformats/go-multiaddr-dns" ) // Define a dns4 format multiaddr -var DNS4 = Base(madns.P_DNS4) +var DNS4 = Base(ma.P_DNS4) // Define a dns6 format multiaddr -var DNS6 = Base(madns.P_DNS6) +var DNS6 = Base(ma.P_DNS6) -// Define a dnsaddr, dns4 or dns6 format multiaddr +// Define a dnsaddr, dns, dns4 or dns6 format multiaddr var DNS = Or( - Base(madns.P_DNSADDR), + Base(ma.P_DNS), + Base(ma.P_DNSADDR), DNS4, DNS6, ) @@ -47,8 +47,13 @@ var Unreliable = Or(UDP) // Now define a Reliable transport as either tcp or utp or quic var Reliable = Or(TCP, UTP, QUIC) +// P2P can run over any reliable underlying transport protocol +var P2P = And(Reliable, Base(ma.P_P2P)) + // IPFS can run over any reliable underlying transport protocol -var IPFS = And(Reliable, Base(ma.P_IPFS)) +// +// Deprecated: use P2P +var IPFS = P2P // Define http over TCP or DNS or http over DNS format multiaddr var HTTP = Or( diff --git a/vendor/github.com/multiformats/go-multiaddr-net/.travis.yml b/vendor/github.com/multiformats/go-multiaddr-net/.travis.yml index 18f4287d7..336deb460 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/.travis.yml +++ b/vendor/github.com/multiformats/go-multiaddr-net/.travis.yml @@ -4,13 +4,12 @@ os: language: go go: - - 1.11.x + - 1.12.x env: global: - GOTFLAGS="-race" matrix: - - BUILD_DEPTYPE=gx - BUILD_DEPTYPE=gomod @@ -24,7 +23,6 @@ script: cache: directories: - - $GOPATH/src/gx - $GOPATH/pkg/mod - /home/travis/.cache/go-build diff --git a/vendor/github.com/multiformats/go-multiaddr-net/README.md b/vendor/github.com/multiformats/go-multiaddr-net/README.md index c13d248fa..e9ad25f8c 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/README.md +++ b/vendor/github.com/multiformats/go-multiaddr-net/README.md @@ -1,6 +1,6 @@ # go-multiaddr-net -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) [![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) @@ -35,21 +35,7 @@ Note that `go-multiaddr-net` is packaged with Gx, so it is recommended to use Gx ## Usage -This module is packaged with [Gx](https://github.com/whyrusleeping/gx). In order to use it in your own project do: - -```sh -go get -u github.com/whyrusleeping/gx -go get -u github.com/whyrusleeping/gx-go -cd -gx init -gx import github.com/multiformats/go-multiaddr-net -gx install --global -gx-go --rewrite -``` - -Please check [Gx](https://github.com/whyrusleeping/gx) and [Gx-go](https://github.com/whyrusleeping/gx-go) documentation for more information. - -For further usage, see the docs: +See the docs: - `multiaddr/net`: https://godoc.org/github.com/multiformats/go-multiaddr-net - `multiaddr`: https://godoc.org/github.com/multiformats/go-multiaddr diff --git a/vendor/github.com/multiformats/go-multiaddr-net/convert.go b/vendor/github.com/multiformats/go-multiaddr-net/convert.go index 061f1c484..b1e544668 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/convert.go +++ b/vendor/github.com/multiformats/go-multiaddr-net/convert.go @@ -6,7 +6,6 @@ import ( "path/filepath" ma "github.com/multiformats/go-multiaddr" - madns "github.com/multiformats/go-multiaddr-dns" ) var errIncorrectNetAddr = fmt.Errorf("incorrect network addr conversion") @@ -131,12 +130,12 @@ func DialArgs(m ma.Multiaddr) (string, string, error) { network = "ip4" ip = c.Value() return true - case madns.Dns4Protocol.Code: + case ma.P_DNS4: network = "ip4" hostname = true ip = c.Value() return true - case madns.Dns6Protocol.Code: + case ma.P_DNS6: network = "ip6" hostname = true ip = c.Value() diff --git a/vendor/github.com/multiformats/go-multiaddr-net/go.mod b/vendor/github.com/multiformats/go-multiaddr-net/go.mod index 57c282747..bb2ec44e4 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/go.mod +++ b/vendor/github.com/multiformats/go-multiaddr-net/go.mod @@ -1,6 +1,5 @@ module github.com/multiformats/go-multiaddr-net -require ( - github.com/multiformats/go-multiaddr v0.0.1 - github.com/multiformats/go-multiaddr-dns v0.0.1 -) +require github.com/multiformats/go-multiaddr v0.1.0 + +go 1.12 diff --git a/vendor/github.com/multiformats/go-multiaddr-net/go.sum b/vendor/github.com/multiformats/go-multiaddr-net/go.sum index fc801cab8..87f7a0940 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/go.sum +++ b/vendor/github.com/multiformats/go-multiaddr-net/go.sum @@ -8,10 +8,8 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XC github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= -github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr-dns v0.0.1 h1:jQt9c6tDSdQLIlBo4tXYx7QUHCPjxsB1zXcag/2S7zc= -github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr v0.1.0 h1:fkISCUNDb3xIpCcI6BGlPsQE+ywcxzimOsUnHWnrE74= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= diff --git a/vendor/github.com/multiformats/go-multiaddr-net/net.go b/vendor/github.com/multiformats/go-multiaddr-net/net.go index ac35530d7..79ad96e84 100644 --- a/vendor/github.com/multiformats/go-multiaddr-net/net.go +++ b/vendor/github.com/multiformats/go-multiaddr-net/net.go @@ -310,14 +310,12 @@ func WrapNetListener(nl net.Listener) (Listener, error) { // A PacketConn is a generic packet oriented network connection which uses an // underlying net.PacketConn, wrapped with the locally bound Multiaddr. type PacketConn interface { - Connection() net.PacketConn + net.PacketConn - Multiaddr() ma.Multiaddr + LocalMultiaddr() ma.Multiaddr - ReadFrom(b []byte) (int, ma.Multiaddr, error) - WriteTo(b []byte, maddr ma.Multiaddr) (int, error) - - Close() error + ReadFromMultiaddr(b []byte) (int, ma.Multiaddr, error) + WriteToMultiaddr(b []byte, maddr ma.Multiaddr) (int, error) } // maPacketConn implements PacketConn @@ -326,28 +324,25 @@ type maPacketConn struct { laddr ma.Multiaddr } -// Connection returns the embedded net.PacketConn. -func (l *maPacketConn) Connection() net.PacketConn { - return l.PacketConn -} +var _ PacketConn = (*maPacketConn)(nil) -// Multiaddr returns the bound local Multiaddr. -func (l *maPacketConn) Multiaddr() ma.Multiaddr { +// LocalMultiaddr returns the bound local Multiaddr. +func (l *maPacketConn) LocalMultiaddr() ma.Multiaddr { return l.laddr } -func (l *maPacketConn) ReadFrom(b []byte) (int, ma.Multiaddr, error) { - n, addr, err := l.PacketConn.ReadFrom(b) +func (l *maPacketConn) ReadFromMultiaddr(b []byte) (int, ma.Multiaddr, error) { + n, addr, err := l.ReadFrom(b) maddr, _ := FromNetAddr(addr) return n, maddr, err } -func (l *maPacketConn) WriteTo(b []byte, maddr ma.Multiaddr) (int, error) { +func (l *maPacketConn) WriteToMultiaddr(b []byte, maddr ma.Multiaddr) (int, error) { addr, err := ToNetAddr(maddr) if err != nil { return 0, err } - return l.PacketConn.WriteTo(b, addr) + return l.WriteTo(b, addr) } // ListenPacket announces on the local network address laddr. diff --git a/vendor/github.com/multiformats/go-multiaddr-net/package.json b/vendor/github.com/multiformats/go-multiaddr-net/package.json deleted file mode 100644 index cdad09eac..000000000 --- a/vendor/github.com/multiformats/go-multiaddr-net/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "author": "multiformats", - "bugs": { - "url": "https://github.com/multiformats/go-multiaddr-net" - }, - "gx": { - "dvcsimport": "github.com/multiformats/go-multiaddr-net" - }, - "gxDependencies": [ - { - "author": "multiformats", - "hash": "QmTZBfrPJmjWsCvHEtX5FE6KimVJhsJg5sBbqEFYf4UZtL", - "name": "go-multiaddr", - "version": "1.4.1" - }, - { - "author": "lgierth", - "hash": "QmU98UaAEh4WJAcir2qjfztU77JQ14kAwHNFkjUXHZA3Vy", - "name": "go-multiaddr-dns", - "version": "0.3.1" - } - ], - "gxVersion": "0.6.0", - "language": "go", - "license": "", - "name": "go-multiaddr-net", - "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "1.7.2" -} - diff --git a/vendor/github.com/multiformats/go-multiaddr/go.mod b/vendor/github.com/multiformats/go-multiaddr/go.mod index debcf3c5d..07d7017e8 100644 --- a/vendor/github.com/multiformats/go-multiaddr/go.mod +++ b/vendor/github.com/multiformats/go-multiaddr/go.mod @@ -1,3 +1,5 @@ module github.com/multiformats/go-multiaddr -require github.com/multiformats/go-multihash v0.0.1 +require github.com/multiformats/go-multihash v0.0.8 + +go 1.12 diff --git a/vendor/github.com/multiformats/go-multiaddr/go.sum b/vendor/github.com/multiformats/go-multiaddr/go.sum index faa395abe..2df8a78f1 100644 --- a/vendor/github.com/multiformats/go-multiaddr/go.sum +++ b/vendor/github.com/multiformats/go-multiaddr/go.sum @@ -1,18 +1,18 @@ -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v1.0.10 h1:KUnC6rT8Vyw0gx4qXUS6VN1QHKrgmvdDCaURVQ7+miM= -github.com/multiformats/go-multihash v1.0.10/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/multiformats/go-multiaddr/protocols.go b/vendor/github.com/multiformats/go-multiaddr/protocols.go index cb38a70e7..a4e062e9c 100644 --- a/vendor/github.com/multiformats/go-multiaddr/protocols.go +++ b/vendor/github.com/multiformats/go-multiaddr/protocols.go @@ -5,12 +5,17 @@ package multiaddr const ( P_IP4 = 0x0004 P_TCP = 0x0006 + P_DNS = 0x0035 // 4 or 6 + P_DNS4 = 0x0036 + P_DNS6 = 0x0037 + P_DNSADDR = 0x0038 P_UDP = 0x0111 P_DCCP = 0x0021 P_IP6 = 0x0029 P_IP6ZONE = 0x002A P_QUIC = 0x01CC P_SCTP = 0x0084 + P_CIRCUIT = 0x0122 P_UDT = 0x012D P_UTP = 0x012E P_UNIX = 0x0190 @@ -23,6 +28,7 @@ const ( P_GARLIC64 = 0x01BE P_GARLIC32 = 0x01BF P_P2P_WEBRTC_DIRECT = 0x0114 + P_WS = 0x01DD ) var ( @@ -42,6 +48,34 @@ var ( Path: false, Transcoder: TranscoderPort, } + protoDNS = Protocol{ + Code: P_DNS, + Size: LengthPrefixedVarSize, + Name: "dns", + VCode: CodeToVarint(P_DNS), + Transcoder: TranscoderDns, + } + protoDNS4 = Protocol{ + Code: P_DNS4, + Size: LengthPrefixedVarSize, + Name: "dns4", + VCode: CodeToVarint(P_DNS4), + Transcoder: TranscoderDns, + } + protoDNS6 = Protocol{ + Code: P_DNS6, + Size: LengthPrefixedVarSize, + Name: "dns6", + VCode: CodeToVarint(P_DNS6), + Transcoder: TranscoderDns, + } + protoDNSADDR = Protocol{ + Code: P_DNSADDR, + Size: LengthPrefixedVarSize, + Name: "dnsaddr", + VCode: CodeToVarint(P_DNSADDR), + Transcoder: TranscoderDns, + } protoUDP = Protocol{ Name: "udp", Code: P_UDP, @@ -81,6 +115,14 @@ var ( Size: 16, Transcoder: TranscoderPort, } + + protoCIRCUIT = Protocol{ + Code: P_CIRCUIT, + Size: 0, + Name: "p2p-circuit", + VCode: CodeToVarint(P_CIRCUIT), + } + protoONION2 = Protocol{ Name: "onion", Code: P_ONION, @@ -154,17 +196,27 @@ var ( Code: P_P2P_WEBRTC_DIRECT, VCode: CodeToVarint(P_P2P_WEBRTC_DIRECT), } + protoWS = Protocol{ + Name: "ws", + Code: P_WS, + VCode: CodeToVarint(P_WS), + } ) func init() { for _, p := range []Protocol{ protoIP4, protoTCP, + protoDNS, + protoDNS4, + protoDNS6, + protoDNSADDR, protoUDP, protoDCCP, protoIP6, protoIP6ZONE, protoSCTP, + protoCIRCUIT, protoONION2, protoONION3, protoGARLIC64, @@ -177,6 +229,7 @@ func init() { protoP2P, protoUNIX, protoP2P_WEBRTC_DIRECT, + protoWS, } { if err := AddProtocol(p); err != nil { panic(err) diff --git a/vendor/github.com/multiformats/go-multiaddr/transcoders.go b/vendor/github.com/multiformats/go-multiaddr/transcoders.go index 77908b705..e1f5b27ea 100644 --- a/vendor/github.com/multiformats/go-multiaddr/transcoders.go +++ b/vendor/github.com/multiformats/go-multiaddr/transcoders.go @@ -317,3 +317,20 @@ func unixStB(s string) ([]byte, error) { func unixBtS(b []byte) (string, error) { return string(b), nil } + +var TranscoderDns = NewTranscoderFromFunctions(dnsStB, dnsBtS, dnsVal) + +func dnsVal(b []byte) error { + if bytes.IndexByte(b, '/') >= 0 { + return fmt.Errorf("domain name %q contains a slash", string(b)) + } + return nil +} + +func dnsStB(s string) ([]byte, error) { + return []byte(s), nil +} + +func dnsBtS(b []byte) (string, error) { + return string(b), nil +} diff --git a/vendor/github.com/multiformats/go-multihash/.gitmodules b/vendor/github.com/multiformats/go-multihash/.gitmodules new file mode 100644 index 000000000..d92ce4f1b --- /dev/null +++ b/vendor/github.com/multiformats/go-multihash/.gitmodules @@ -0,0 +1,6 @@ +[submodule "spec/multicodec"] + path = spec/multicodec + url = https://github.com/multiformats/multicodec.git +[submodule "spec/multihash"] + path = spec/multihash + url = https://github.com/multiformats/multihash.git diff --git a/vendor/github.com/multiformats/go-multihash/go.mod b/vendor/github.com/multiformats/go-multihash/go.mod index e96dee1dc..f62491fdf 100644 --- a/vendor/github.com/multiformats/go-multihash/go.mod +++ b/vendor/github.com/multiformats/go-multihash/go.mod @@ -2,8 +2,10 @@ module github.com/multiformats/go-multihash require ( github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 - github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 + github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 github.com/mr-tron/base58 v1.1.2 github.com/spaolacci/murmur3 v1.1.0 - golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 + golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 ) + +go 1.13 diff --git a/vendor/github.com/multiformats/go-multihash/go.sum b/vendor/github.com/multiformats/go-multihash/go.sum index c75498949..2beea9d58 100644 --- a/vendor/github.com/multiformats/go-multihash/go.sum +++ b/vendor/github.com/multiformats/go-multihash/go.sum @@ -1,14 +1,14 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= diff --git a/vendor/github.com/multiformats/go-multihash/multihash.go b/vendor/github.com/multiformats/go-multihash/multihash.go index 54d90153e..52c2f563a 100644 --- a/vendor/github.com/multiformats/go-multihash/multihash.go +++ b/vendor/github.com/multiformats/go-multihash/multihash.go @@ -31,12 +31,14 @@ type ErrInconsistentLen struct { } func (e ErrInconsistentLen) Error() string { - return fmt.Sprintf("multihash length inconsistent: %v", e.dm) + return fmt.Sprintf("multihash length inconsistent: expected %d, got %d", e.dm.Length, len(e.dm.Digest)) } // constants const ( - ID = 0x00 + IDENTITY = 0x00 + // Deprecated: use IDENTITY + ID = IDENTITY SHA1 = 0x11 SHA2_256 = 0x12 SHA2_512 = 0x13 @@ -62,7 +64,9 @@ const ( DBL_SHA2_256 = 0x56 - MURMUR3 = 0x22 + MURMUR3_128 = 0x22 + // Deprecated: use MURMUR3_128 + MURMUR3 = MURMUR3_128 X11 = 0x1100 ) @@ -89,7 +93,7 @@ func init() { // Names maps the name of a hash to the code var Names = map[string]uint64{ - "id": ID, + "identity": IDENTITY, "sha1": SHA1, "sha2-256": SHA2_256, "sha2-512": SHA2_512, @@ -99,7 +103,7 @@ var Names = map[string]uint64{ "sha3-384": SHA3_384, "sha3-512": SHA3_512, "dbl-sha2-256": DBL_SHA2_256, - "murmur3": MURMUR3, + "murmur3-128": MURMUR3_128, "keccak-224": KECCAK_224, "keccak-256": KECCAK_256, "keccak-384": KECCAK_384, @@ -112,7 +116,7 @@ var Names = map[string]uint64{ // Codes maps a hash code to it's name var Codes = map[uint64]string{ - ID: "id", + IDENTITY: "identity", SHA1: "sha1", SHA2_256: "sha2-256", SHA2_512: "sha2-512", @@ -121,7 +125,7 @@ var Codes = map[uint64]string{ SHA3_384: "sha3-384", SHA3_512: "sha3-512", DBL_SHA2_256: "dbl-sha2-256", - MURMUR3: "murmur3", + MURMUR3_128: "murmur3-128", KECCAK_224: "keccak-224", KECCAK_256: "keccak-256", KECCAK_384: "keccak-384", @@ -134,7 +138,7 @@ var Codes = map[uint64]string{ // DefaultLengths maps a hash code to it's default length var DefaultLengths = map[uint64]int{ - ID: -1, + IDENTITY: -1, SHA1: 20, SHA2_256: 32, SHA2_512: 64, @@ -145,7 +149,7 @@ var DefaultLengths = map[uint64]int{ DBL_SHA2_256: 32, KECCAK_224: 28, KECCAK_256: 32, - MURMUR3: 4, + MURMUR3_128: 4, KECCAK_384: 48, KECCAK_512: 64, SHAKE_128: 32, diff --git a/vendor/github.com/multiformats/go-multihash/sum.go b/vendor/github.com/multiformats/go-multihash/sum.go index 249cb7577..bfc2043ba 100644 --- a/vendor/github.com/multiformats/go-multihash/sum.go +++ b/vendor/github.com/multiformats/go-multihash/sum.go @@ -167,7 +167,7 @@ func sumSHA3_224(data []byte, length int) ([]byte, error) { } func registerStdlibHashFuncs() { - RegisterHashFunc(ID, sumID) + RegisterHashFunc(IDENTITY, sumID) RegisterHashFunc(SHA1, sumSHA1) RegisterHashFunc(SHA2_512, sumSHA512) RegisterHashFunc(MD5, sumMD5) @@ -185,7 +185,7 @@ func registerNonStdlibHashFuncs() { RegisterHashFunc(SHA3_384, sumSHA3_384) RegisterHashFunc(SHA3_512, sumSHA3_512) - RegisterHashFunc(MURMUR3, sumMURMUR3) + RegisterHashFunc(MURMUR3_128, sumMURMUR3) RegisterHashFunc(SHAKE_128, sumSHAKE128) RegisterHashFunc(SHAKE_256, sumSHAKE256) diff --git a/vendor/github.com/olekukonko/tablewriter/.travis.yml b/vendor/github.com/olekukonko/tablewriter/.travis.yml new file mode 100644 index 000000000..354b7f8b2 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - tip diff --git a/vendor/github.com/libp2p/go-libp2p-crypto/LICENSE b/vendor/github.com/olekukonko/tablewriter/LICENCE.md similarity index 93% rename from vendor/github.com/libp2p/go-libp2p-crypto/LICENSE rename to vendor/github.com/olekukonko/tablewriter/LICENCE.md index 26100332b..1fd848425 100644 --- a/vendor/github.com/libp2p/go-libp2p-crypto/LICENSE +++ b/vendor/github.com/olekukonko/tablewriter/LICENCE.md @@ -1,6 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2016 Jeromy Johnson +Copyright (C) 2014 by Oleku Konko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +16,4 @@ 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. +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md new file mode 100644 index 000000000..805330adc --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -0,0 +1,204 @@ +ASCII Table Writer +========= + +[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) [![Total views](https://sourcegraph.com/api/repos/github.com/olekukonko/tablewriter/counters/views.png)](https://sourcegraph.com/github.com/olekukonko/tablewriter) + +Generate ASCII table on the fly ... Installation is simple as + + go get github.com/olekukonko/tablewriter + + +#### Features +- Automatic Padding +- Support Multiple Lines +- Supports Alignment +- Support Custom Separators +- Automatic Alignment of numbers & percentage +- Write directly to http , file etc via `io.Writer` +- Read directly from CSV file +- Optional row line via `SetRowLine` +- Normalise table header +- Make CSV Headers optional +- Enable or disable table border +- Set custom footer support +- Optional identical cells merging + + +#### Example 1 - Basic +```go +data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) + +for _, v := range data { + table.Append(v) +} +table.Render() // Send output +``` + +##### Output 1 +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +``` + +#### Example 2 - Without Border / Footer / Bulk Append +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.SetBorder(false) // Set Border to false +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 2 +``` + + DATE | DESCRIPTION | CV2 | AMOUNT ++----------+--------------------------+-------+---------+ + 1/1/2014 | Domain name | 2233 | $10.98 + 1/1/2014 | January Hosting | 2233 | $54.95 + 1/4/2014 | February Hosting | 2233 | $51.00 + 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 ++----------+--------------------------+-------+---------+ + TOTAL | $146 93 + +-------+---------+ + +``` + + +#### Example 3 - CSV +```go +table, _ := tablewriter.NewCSV(os.Stdout, "test_info.csv", true) +table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment +table.Render() +``` + +##### Output 3 +``` ++----------+--------------+------+-----+---------+----------------+ +| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | ++----------+--------------+------+-----+---------+----------------+ +| user_id | smallint(5) | NO | PRI | NULL | auto_increment | +| username | varchar(10) | NO | | NULL | | +| password | varchar(100) | NO | | NULL | | ++----------+--------------+------+-----+---------+----------------+ +``` + +#### Example 4 - Custom Separator +```go +table, _ := tablewriter.NewCSV(os.Stdout, "test.csv", true) +table.SetRowLine(true) // Enable row line + +// Change table lines +table.SetCenterSeparator("*") +table.SetColumnSeparator("‡") +table.SetRowSeparator("-") + +table.SetAlignment(tablewriter.ALIGN_LEFT) +table.Render() +``` + +##### Output 4 +``` +*------------*-----------*---------* +╪ FIRST NAME ╪ LAST NAME ╪ SSN ╪ +*------------*-----------*---------* +╪ John ╪ Barry ╪ 123456 ╪ +*------------*-----------*---------* +╪ Kathy ╪ Smith ╪ 687987 ╪ +*------------*-----------*---------* +╪ Bob ╪ McCornick ╪ 3979870 ╪ +*------------*-----------*---------* +``` + +##### Example 5 - Markdown Format +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) +table.SetCenterSeparator("|") +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 5 +``` +| DATE | DESCRIPTION | CV2 | AMOUNT | +|----------|--------------------------|------|--------| +| 1/1/2014 | Domain name | 2233 | $10.98 | +| 1/1/2014 | January Hosting | 2233 | $54.95 | +| 1/4/2014 | February Hosting | 2233 | $51.00 | +| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +``` + +#### Example 6 - Identical cells merging +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "1234", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2345", "$54.95"}, + []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCells(true) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 6 +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++ +--------------------------+-------+---------+ +| | January Hosting | 2345 | $54.95 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++ +--------------------------+-------+---------+ +| | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146 93 | ++----------+--------------------------+-------+---------+ +``` + +#### TODO +- ~~Import Directly from CSV~~ - `done` +- ~~Support for `SetFooter`~~ - `done` +- ~~Support for `SetBorder`~~ - `done` +- ~~Support table with uneven rows~~ - `done` +- Support custom alignment +- General Improvement & Optimisation +- `NewHTML` Parse table from HTML diff --git a/vendor/github.com/olekukonko/tablewriter/csv.go b/vendor/github.com/olekukonko/tablewriter/csv.go new file mode 100644 index 000000000..98878303b --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/csv.go @@ -0,0 +1,52 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "encoding/csv" + "io" + "os" +) + +// Start A new table by importing from a CSV file +// Takes io.Writer and csv File name +func NewCSV(writer io.Writer, fileName string, hasHeader bool) (*Table, error) { + file, err := os.Open(fileName) + if err != nil { + return &Table{}, err + } + defer file.Close() + csvReader := csv.NewReader(file) + t, err := NewCSVReader(writer, csvReader, hasHeader) + return t, err +} + +// Start a New Table Writer with csv.Reader +// This enables customisation such as reader.Comma = ';' +// See http://golang.org/src/pkg/encoding/csv/reader.go?s=3213:3671#L94 +func NewCSVReader(writer io.Writer, csvReader *csv.Reader, hasHeader bool) (*Table, error) { + t := NewWriter(writer) + if hasHeader { + // Read the first row + headers, err := csvReader.Read() + if err != nil { + return &Table{}, err + } + t.SetHeader(headers) + } + for { + record, err := csvReader.Read() + if err == io.EOF { + break + } else if err != nil { + return &Table{}, err + } + t.Append(record) + } + return t, nil +} diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go new file mode 100644 index 000000000..3314bfba5 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -0,0 +1,662 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +// Create & Generate text based table +package tablewriter + +import ( + "bytes" + "fmt" + "io" + "regexp" + "strings" +) + +const ( + MAX_ROW_WIDTH = 30 +) + +const ( + CENTER = "+" + ROW = "-" + COLUMN = "|" + SPACE = " " + NEWLINE = "\n" +) + +const ( + ALIGN_DEFAULT = iota + ALIGN_CENTER + ALIGN_RIGHT + ALIGN_LEFT +) + +var ( + decimal = regexp.MustCompile(`^-*\d*\.?\d*$`) + percent = regexp.MustCompile(`^-*\d*\.?\d*$%$`) +) + +type Border struct { + Left bool + Right bool + Top bool + Bottom bool +} + +type Table struct { + out io.Writer + rows [][]string + lines [][][]string + cs map[int]int + rs map[int]int + headers []string + footers []string + autoFmt bool + autoWrap bool + mW int + pCenter string + pRow string + pColumn string + tColumn int + tRow int + hAlign int + fAlign int + align int + newLine string + rowLine bool + autoMergeCells bool + hdrLine bool + borders Border + colSize int +} + +// Start New Table +// Take io.Writer Directly +func NewWriter(writer io.Writer) *Table { + t := &Table{ + out: writer, + rows: [][]string{}, + lines: [][][]string{}, + cs: make(map[int]int), + rs: make(map[int]int), + headers: []string{}, + footers: []string{}, + autoFmt: true, + autoWrap: true, + mW: MAX_ROW_WIDTH, + pCenter: CENTER, + pRow: ROW, + pColumn: COLUMN, + tColumn: -1, + tRow: -1, + hAlign: ALIGN_DEFAULT, + fAlign: ALIGN_DEFAULT, + align: ALIGN_DEFAULT, + newLine: NEWLINE, + rowLine: false, + hdrLine: true, + borders: Border{Left: true, Right: true, Bottom: true, Top: true}, + colSize: -1} + return t +} + +// Render table output +func (t Table) Render() { + if t.borders.Top { + t.printLine(true) + } + t.printHeading() + if t.autoMergeCells { + t.printRowsMergeCells() + } else { + t.printRows() + } + + if !t.rowLine && t.borders.Bottom { + t.printLine(true) + } + t.printFooter() + +} + +// Set table header +func (t *Table) SetHeader(keys []string) { + t.colSize = len(keys) + for i, v := range keys { + t.parseDimension(v, i, -1) + t.headers = append(t.headers, v) + } +} + +// Set table Footer +func (t *Table) SetFooter(keys []string) { + //t.colSize = len(keys) + for i, v := range keys { + t.parseDimension(v, i, -1) + t.footers = append(t.footers, v) + } +} + +// Turn header autoformatting on/off. Default is on (true). +func (t *Table) SetAutoFormatHeaders(auto bool) { + t.autoFmt = auto +} + +// Turn automatic multiline text adjustment on/off. Default is on (true). +func (t *Table) SetAutoWrapText(auto bool) { + t.autoWrap = auto +} + +// Set the Default column width +func (t *Table) SetColWidth(width int) { + t.mW = width +} + +// Set the Column Separator +func (t *Table) SetColumnSeparator(sep string) { + t.pColumn = sep +} + +// Set the Row Separator +func (t *Table) SetRowSeparator(sep string) { + t.pRow = sep +} + +// Set the center Separator +func (t *Table) SetCenterSeparator(sep string) { + t.pCenter = sep +} + +// Set Header Alignment +func (t *Table) SetHeaderAlignment(hAlign int) { + t.hAlign = hAlign +} + +// Set Footer Alignment +func (t *Table) SetFooterAlignment(fAlign int) { + t.fAlign = fAlign +} + +// Set Table Alignment +func (t *Table) SetAlignment(align int) { + t.align = align +} + +// Set New Line +func (t *Table) SetNewLine(nl string) { + t.newLine = nl +} + +// Set Header Line +// This would enable / disable a line after the header +func (t *Table) SetHeaderLine(line bool) { + t.hdrLine = line +} + +// Set Row Line +// This would enable / disable a line on each row of the table +func (t *Table) SetRowLine(line bool) { + t.rowLine = line +} + +// Set Auto Merge Cells +// This would enable / disable the merge of cells with identical values +func (t *Table) SetAutoMergeCells(auto bool) { + t.autoMergeCells = auto +} + +// Set Table Border +// This would enable / disable line around the table +func (t *Table) SetBorder(border bool) { + t.SetBorders(Border{border, border, border, border}) +} + +func (t *Table) SetBorders(border Border) { + t.borders = border +} + +// Append row to table +func (t *Table) Append(row []string) { + rowSize := len(t.headers) + if rowSize > t.colSize { + t.colSize = rowSize + } + + n := len(t.lines) + line := [][]string{} + for i, v := range row { + + // Detect string width + // Detect String height + // Break strings into words + out := t.parseDimension(v, i, n) + + // Append broken words + line = append(line, out) + } + t.lines = append(t.lines, line) +} + +// Allow Support for Bulk Append +// Eliminates repeated for loops +func (t *Table) AppendBulk(rows [][]string) { + for _, row := range rows { + t.Append(row) + } +} + +// Print line based on row width +func (t Table) printLine(nl bool) { + fmt.Fprint(t.out, t.pCenter) + for i := 0; i < len(t.cs); i++ { + v := t.cs[i] + fmt.Fprintf(t.out, "%s%s%s%s", + t.pRow, + strings.Repeat(string(t.pRow), v), + t.pRow, + t.pCenter) + } + if nl { + fmt.Fprint(t.out, t.newLine) + } +} + +// Print line based on row width with our without cell separator +func (t Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { + fmt.Fprint(t.out, t.pCenter) + for i := 0; i < len(t.cs); i++ { + v := t.cs[i] + if i > len(displayCellSeparator) || displayCellSeparator[i] { + // Display the cell separator + fmt.Fprintf(t.out, "%s%s%s%s", + t.pRow, + strings.Repeat(string(t.pRow), v), + t.pRow, + t.pCenter) + } else { + // Don't display the cell separator for this cell + fmt.Fprintf(t.out, "%s%s", + strings.Repeat(" ", v+2), + t.pCenter) + } + } + if nl { + fmt.Fprint(t.out, t.newLine) + } +} + +// Return the PadRight function if align is left, PadLeft if align is right, +// and Pad by default +func pad(align int) func(string, string, int) string { + padFunc := Pad + switch align { + case ALIGN_LEFT: + padFunc = PadRight + case ALIGN_RIGHT: + padFunc = PadLeft + } + return padFunc +} + +// Print heading information +func (t Table) printHeading() { + // Check if headers is available + if len(t.headers) < 1 { + return + } + + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + + // Identify last column + end := len(t.cs) - 1 + + // Get pad function + padFunc := pad(t.hAlign) + + // Print Heading column + for i := 0; i <= end; i++ { + v := t.cs[i] + h := t.headers[i] + if t.autoFmt { + h = Title(h) + } + pad := ConditionString((i == end && !t.borders.Left), SPACE, t.pColumn) + fmt.Fprintf(t.out, " %s %s", + padFunc(h, SPACE, v), + pad) + } + // Next line + fmt.Fprint(t.out, t.newLine) + if t.hdrLine { + t.printLine(true) + } +} + +// Print heading information +func (t Table) printFooter() { + // Check if headers is available + if len(t.footers) < 1 { + return + } + + // Only print line if border is not set + if !t.borders.Bottom { + t.printLine(true) + } + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) + + // Identify last column + end := len(t.cs) - 1 + + // Get pad function + padFunc := pad(t.fAlign) + + // Print Heading column + for i := 0; i <= end; i++ { + v := t.cs[i] + f := t.footers[i] + if t.autoFmt { + f = Title(f) + } + pad := ConditionString((i == end && !t.borders.Top), SPACE, t.pColumn) + + if len(t.footers[i]) == 0 { + pad = SPACE + } + fmt.Fprintf(t.out, " %s %s", + padFunc(f, SPACE, v), + pad) + } + // Next line + fmt.Fprint(t.out, t.newLine) + //t.printLine(true) + + hasPrinted := false + + for i := 0; i <= end; i++ { + v := t.cs[i] + pad := t.pRow + center := t.pCenter + length := len(t.footers[i]) + + if length > 0 { + hasPrinted = true + } + + // Set center to be space if length is 0 + if length == 0 && !t.borders.Right { + center = SPACE + } + + // Print first junction + if i == 0 { + fmt.Fprint(t.out, center) + } + + // Pad With space of length is 0 + if length == 0 { + pad = SPACE + } + // Ignore left space of it has printed before + if hasPrinted || t.borders.Left { + pad = t.pRow + center = t.pCenter + } + + // Change Center start position + if center == SPACE { + if i < end && len(t.footers[i+1]) != 0 { + center = t.pCenter + } + } + + // Print the footer + fmt.Fprintf(t.out, "%s%s%s%s", + pad, + strings.Repeat(string(pad), v), + pad, + center) + + } + + fmt.Fprint(t.out, t.newLine) + +} + +func (t Table) printRows() { + for i, lines := range t.lines { + t.printRow(lines, i) + } + +} + +// Print Row Information +// Adjust column alignment based on type + +func (t Table) printRow(columns [][]string, colKey int) { + // Get Maximum Height + max := t.rs[colKey] + total := len(columns) + + // TODO Fix uneven col size + // if total < t.colSize { + // for n := t.colSize - total; n < t.colSize ; n++ { + // columns = append(columns, []string{SPACE}) + // t.cs[n] = t.mW + // } + //} + + // Pad Each Height + // pads := []int{} + pads := []int{} + + for i, line := range columns { + length := len(line) + pad := max - length + pads = append(pads, pad) + for n := 0; n < pad; n++ { + columns[i] = append(columns[i], " ") + } + } + //fmt.Println(max, "\n") + for x := 0; x < max; x++ { + for y := 0; y < total; y++ { + + // Check if border is set + fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + + fmt.Fprintf(t.out, SPACE) + str := columns[y][x] + + // This would print alignment + // Default alignment would use multiple configuration + switch t.align { + case ALIGN_CENTER: // + fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) + case ALIGN_RIGHT: + fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) + case ALIGN_LEFT: + fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + default: + if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { + fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) + } else { + fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + + // TODO Custom alignment per column + //if max == 1 || pads[y] > 0 { + // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) + //} else { + // fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + //} + + } + } + fmt.Fprintf(t.out, SPACE) + } + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + fmt.Fprint(t.out, t.newLine) + } + + if t.rowLine { + t.printLine(true) + } +} + +// Print the rows of the table and merge the cells that are identical +func (t Table) printRowsMergeCells() { + var previousLine []string + var displayCellBorder []bool + var tmpWriter bytes.Buffer + for i, lines := range t.lines { + // We store the display of the current line in a tmp writer, as we need to know which border needs to be print above + previousLine, displayCellBorder = t.printRowMergeCells(&tmpWriter, lines, i, previousLine) + if i > 0 { //We don't need to print borders above first line + if t.rowLine { + t.printLineOptionalCellSeparators(true, displayCellBorder) + } + } + tmpWriter.WriteTo(t.out) + } + //Print the end of the table + if t.rowLine { + t.printLine(true) + } +} + +// Print Row Information to a writer and merge identical cells. +// Adjust column alignment based on type + +func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey int, previousLine []string) ([]string, []bool) { + // Get Maximum Height + max := t.rs[colKey] + total := len(columns) + + // Pad Each Height + pads := []int{} + + for i, line := range columns { + length := len(line) + pad := max - length + pads = append(pads, pad) + for n := 0; n < pad; n++ { + columns[i] = append(columns[i], " ") + } + } + + var displayCellBorder []bool + for x := 0; x < max; x++ { + for y := 0; y < total; y++ { + + // Check if border is set + fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + + fmt.Fprintf(writer, SPACE) + + str := columns[y][x] + + if t.autoMergeCells { + //Store the full line to merge mutli-lines cells + fullLine := strings.Join(columns[y], " ") + if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { + // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. + displayCellBorder = append(displayCellBorder, false) + str = "" + } else { + // First line or different content, keep the content and print the cell border + displayCellBorder = append(displayCellBorder, true) + } + } + + // This would print alignment + // Default alignment would use multiple configuration + switch t.align { + case ALIGN_CENTER: // + fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y])) + case ALIGN_RIGHT: + fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) + case ALIGN_LEFT: + fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) + default: + if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { + fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) + } else { + fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) + } + } + fmt.Fprintf(writer, SPACE) + } + // Check if border is set + // Replace with space if not set + fmt.Fprint(writer, ConditionString(t.borders.Left, t.pColumn, SPACE)) + fmt.Fprint(writer, t.newLine) + } + + //The new previous line is the current one + previousLine = make([]string, total) + for y := 0; y < total; y++ { + previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + } + //Returns the newly added line and wether or not a border should be displayed above. + return previousLine, displayCellBorder +} + +func (t *Table) parseDimension(str string, colKey, rowKey int) []string { + var ( + raw []string + max int + ) + w := DisplayWidth(str) + // Calculate Width + // Check if with is grater than maximum width + if w > t.mW { + w = t.mW + } + + // Check if width exists + v, ok := t.cs[colKey] + if !ok || v < w || v == 0 { + t.cs[colKey] = w + } + + if rowKey == -1 { + return raw + } + // Calculate Height + if t.autoWrap { + raw, _ = WrapString(str, t.cs[colKey]) + } else { + raw = getLines(str) + } + + for _, line := range raw { + if w := DisplayWidth(line); w > max { + max = w + } + } + + // Make sure the with is the same length as maximum word + // Important for cases where the width is smaller than maxu word + if max > t.cs[colKey] { + t.cs[colKey] = max + } + + h := len(raw) + v, ok = t.rs[rowKey] + + if !ok || v < h || v == 0 { + t.rs[rowKey] = h + } + //fmt.Printf("Raw %+v %d\n", raw, len(raw)) + return raw +} diff --git a/vendor/github.com/olekukonko/tablewriter/test.csv b/vendor/github.com/olekukonko/tablewriter/test.csv new file mode 100644 index 000000000..1609327e9 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/test.csv @@ -0,0 +1,4 @@ +first_name,last_name,ssn +John,Barry,123456 +Kathy,Smith,687987 +Bob,McCornick,3979870 \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/test_info.csv b/vendor/github.com/olekukonko/tablewriter/test_info.csv new file mode 100644 index 000000000..e4c40e983 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/test_info.csv @@ -0,0 +1,4 @@ +Field,Type,Null,Key,Default,Extra +user_id,smallint(5),NO,PRI,NULL,auto_increment +username,varchar(10),NO,,NULL, +password,varchar(100),NO,,NULL, \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/util.go b/vendor/github.com/olekukonko/tablewriter/util.go new file mode 100644 index 000000000..2deefbc52 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/util.go @@ -0,0 +1,72 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "math" + "regexp" + "strings" + + "github.com/mattn/go-runewidth" +) + +var ansi = regexp.MustCompile("\033\\[(?:[0-9]{1,3}(?:;[0-9]{1,3})*)?[m|K]") + +func DisplayWidth(str string) int { + return runewidth.StringWidth(ansi.ReplaceAllLiteralString(str, "")) +} + +// Simple Condition for string +// Returns value based on condition +func ConditionString(cond bool, valid, inValid string) string { + if cond { + return valid + } + return inValid +} + +// Format Table Header +// Replace _ , . and spaces +func Title(name string) string { + name = strings.Replace(name, "_", " ", -1) + name = strings.Replace(name, ".", " ", -1) + name = strings.TrimSpace(name) + return strings.ToUpper(name) +} + +// Pad String +// Attempts to play string in the center +func Pad(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + gapLeft := int(math.Ceil(float64(gap / 2))) + gapRight := gap - gapLeft + return strings.Repeat(string(pad), gapLeft) + s + strings.Repeat(string(pad), gapRight) + } + return s +} + +// Pad String Right position +// This would pace string at the left side fo the screen +func PadRight(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + return s + strings.Repeat(string(pad), gap) + } + return s +} + +// Pad String Left position +// This would pace string at the right side fo the screen +func PadLeft(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + return strings.Repeat(string(pad), gap) + s + } + return s +} diff --git a/vendor/github.com/olekukonko/tablewriter/wrap.go b/vendor/github.com/olekukonko/tablewriter/wrap.go new file mode 100644 index 000000000..5290fb65a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/wrap.go @@ -0,0 +1,103 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "math" + "strings" + "unicode/utf8" +) + +var ( + nl = "\n" + sp = " " +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapString(s string, lim int) ([]string, int) { + words := strings.Split(strings.Replace(s, nl, sp, -1), sp) + var lines []string + max := 0 + for _, v := range words { + max = len(v) + if max > lim { + lim = max + } + } + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, strings.Join(line, sp)) + } + return lines, lim +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, +// WrapString will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each rune as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words []string, spc, lim, pen int) [][]string { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = utf8.RuneCountInString(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + utf8.RuneCountInString(words[j]) + } + } + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + var lines [][]string + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} + +// getLines decomposes a multiline string into a slice of strings. +func getLines(s string) []string { + var lines []string + + for _, line := range strings.Split(s, nl) { + lines = append(lines, line) + } + return lines +} diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml index d8156a60b..3deb4a124 100644 --- a/vendor/github.com/pborman/uuid/.travis.yml +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -1,8 +1,9 @@ language: go go: - - 1.4.3 - - 1.5.3 + - "1.9" + - "1.10" + - "1.11" - tip script: diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md index b0396b274..810ad40dc 100644 --- a/vendor/github.com/pborman/uuid/README.md +++ b/vendor/github.com/pborman/uuid/README.md @@ -3,6 +3,8 @@ This project was automatically exported from code.google.com/p/go-uuid # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. +This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). + ###### Install `go get github.com/pborman/uuid` diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go index d8bd013e6..727d76167 100644 --- a/vendor/github.com/pborman/uuid/doc.go +++ b/vendor/github.com/pborman/uuid/doc.go @@ -4,5 +4,10 @@ // The uuid package generates and inspects UUIDs. // -// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// This package is a partial wrapper around the github.com/google/uuid package. +// This package represents a UUID as []byte while github.com/google/uuid +// represents a UUID as [16]byte. package uuid diff --git a/vendor/github.com/pborman/uuid/go.mod b/vendor/github.com/pborman/uuid/go.mod new file mode 100644 index 000000000..099fc7de0 --- /dev/null +++ b/vendor/github.com/pborman/uuid/go.mod @@ -0,0 +1,3 @@ +module github.com/pborman/uuid + +require github.com/google/uuid v1.0.0 diff --git a/vendor/github.com/pborman/uuid/go.sum b/vendor/github.com/pborman/uuid/go.sum new file mode 100644 index 000000000..db2574a9c --- /dev/null +++ b/vendor/github.com/pborman/uuid/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/vendor/github.com/pborman/uuid/marshal.go b/vendor/github.com/pborman/uuid/marshal.go index 6621dd54b..35b89352a 100644 --- a/vendor/github.com/pborman/uuid/marshal.go +++ b/vendor/github.com/pborman/uuid/marshal.go @@ -7,6 +7,8 @@ package uuid import ( "errors" "fmt" + + guuid "github.com/google/uuid" ) // MarshalText implements encoding.TextMarshaler. @@ -60,11 +62,11 @@ func (u Array) MarshalText() ([]byte, error) { // UnmarshalText implements encoding.TextUnmarshaler. func (u *Array) UnmarshalText(data []byte) error { - id := Parse(string(data)) - if id == nil { - return errors.New("invalid UUID") + id, err := guuid.ParseBytes(data) + if err != nil { + return err } - *u = id.Array() + *u = Array(id) return nil } diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go index 42d60da8f..e524e0101 100644 --- a/vendor/github.com/pborman/uuid/node.go +++ b/vendor/github.com/pborman/uuid/node.go @@ -5,24 +5,14 @@ package uuid import ( - "net" - "sync" -) - -var ( - nodeMu sync.Mutex - interfaces []net.Interface // cached list of interfaces - ifname string // name of interface being used - nodeID []byte // hardware for version 1 UUIDs + guuid "github.com/google/uuid" ) // NodeInterface returns the name of the interface from which the NodeID was // derived. The interface "user" is returned if the NodeID was set by // SetNodeID. func NodeInterface() string { - defer nodeMu.Unlock() - nodeMu.Lock() - return ifname + return guuid.NodeInterface() } // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. @@ -32,77 +22,20 @@ func NodeInterface() string { // // SetNodeInterface never fails when name is "". func SetNodeInterface(name string) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - return setNodeInterface(name) -} - -func setNodeInterface(name string) bool { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil && name != "" { - return false - } - } - - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - if setNodeID(ifs.HardwareAddr) { - ifname = ifs.Name - return true - } - } - } - - // We found no interfaces with a valid hardware address. If name - // does not specify a specific interface generate a random Node ID - // (section 4.1.6) - if name == "" { - if nodeID == nil { - nodeID = make([]byte, 6) - } - randomBits(nodeID) - return true - } - return false + return guuid.SetNodeInterface(name) } // NodeID returns a slice of a copy of the current Node ID, setting the Node ID // if not already set. func NodeID() []byte { - defer nodeMu.Unlock() - nodeMu.Lock() - if nodeID == nil { - setNodeInterface("") - } - nid := make([]byte, 6) - copy(nid, nodeID) - return nid + return guuid.NodeID() } // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // of id are used. If id is less than 6 bytes then false is returned and the // Node ID is not set. func SetNodeID(id []byte) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - if setNodeID(id) { - ifname = "user" - return true - } - return false -} - -func setNodeID(id []byte) bool { - if len(id) < 6 { - return false - } - if nodeID == nil { - nodeID = make([]byte, 6) - } - copy(nodeID, id) - return true + return guuid.SetNodeID(id) } // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is diff --git a/vendor/github.com/pborman/uuid/sql.go b/vendor/github.com/pborman/uuid/sql.go index d015bfd13..929c3847e 100644 --- a/vendor/github.com/pborman/uuid/sql.go +++ b/vendor/github.com/pborman/uuid/sql.go @@ -40,7 +40,9 @@ func (uuid *UUID) Scan(src interface{}) error { // assumes a simple slice of bytes if 16 bytes // otherwise attempts to parse if len(b) == 16 { - *uuid = UUID(b) + parsed := make([]byte, 16) + copy(parsed, b) + *uuid = UUID(parsed) } else { u := Parse(string(b)) diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go index eedf24219..5c0960d87 100644 --- a/vendor/github.com/pborman/uuid/time.go +++ b/vendor/github.com/pborman/uuid/time.go @@ -6,65 +6,18 @@ package uuid import ( "encoding/binary" - "sync" - "time" + + guuid "github.com/google/uuid" ) // A Time represents a time as the number of 100's of nanoseconds since 15 Oct // 1582. -type Time int64 - -const ( - lillian = 2299160 // Julian day of 15 Oct 1582 - unix = 2440587 // Julian day of 1 Jan 1970 - epoch = unix - lillian // Days between epochs - g1582 = epoch * 86400 // seconds between epochs - g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs -) - -var ( - timeMu sync.Mutex - lasttime uint64 // last time we returned - clock_seq uint16 // clock sequence for this run - - timeNow = time.Now // for testing -) - -// UnixTime converts t the number of seconds and nanoseconds using the Unix -// epoch of 1 Jan 1970. -func (t Time) UnixTime() (sec, nsec int64) { - sec = int64(t - g1582ns100) - nsec = (sec % 10000000) * 100 - sec /= 10000000 - return sec, nsec -} +type Time = guuid.Time // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and // clock sequence as well as adjusting the clock sequence as needed. An error // is returned if the current time cannot be determined. -func GetTime() (Time, uint16, error) { - defer timeMu.Unlock() - timeMu.Lock() - return getTime() -} - -func getTime() (Time, uint16, error) { - t := timeNow() - - // If we don't have a clock sequence already, set one. - if clock_seq == 0 { - setClockSequence(-1) - } - now := uint64(t.UnixNano()/100) + g1582ns100 - - // If time has gone backwards with this clock sequence then we - // increment the clock sequence - if now <= lasttime { - clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 - } - lasttime = now - return Time(now), clock_seq, nil -} +func GetTime() (Time, uint16, error) { return guuid.GetTime() } // ClockSequence returns the current clock sequence, generating one if not // already set. The clock sequence is only used for Version 1 UUIDs. @@ -74,39 +27,11 @@ func getTime() (Time, uint16, error) { // clock sequence is generated the first time a clock sequence is requested by // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated // for -func ClockSequence() int { - defer timeMu.Unlock() - timeMu.Lock() - return clockSequence() -} - -func clockSequence() int { - if clock_seq == 0 { - setClockSequence(-1) - } - return int(clock_seq & 0x3fff) -} +func ClockSequence() int { return guuid.ClockSequence() } // SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to // -1 causes a new sequence to be generated. -func SetClockSequence(seq int) { - defer timeMu.Unlock() - timeMu.Lock() - setClockSequence(seq) -} - -func setClockSequence(seq int) { - if seq == -1 { - var b [2]byte - randomBits(b[:]) // clock sequence - seq = int(b[0])<<8 | int(b[1]) - } - old_seq := clock_seq - clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if old_seq != clock_seq { - lasttime = 0 - } -} +func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in // uuid. It returns false if uuid is not valid. The time is only well defined diff --git a/vendor/github.com/pborman/uuid/util.go b/vendor/github.com/pborman/uuid/util.go index fc8e052c7..255b5e248 100644 --- a/vendor/github.com/pborman/uuid/util.go +++ b/vendor/github.com/pborman/uuid/util.go @@ -4,17 +4,6 @@ package uuid -import ( - "io" -) - -// randomBits completely fills slice b with random data. -func randomBits(b []byte) { - if _, err := io.ReadFull(rander, b); err != nil { - panic(err.Error()) // rand should never fail - } -} - // xvalues returns the value of a byte as a hexadecimal digit or 255. var xvalues = [256]byte{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go index 7c643cf0a..337000420 100644 --- a/vendor/github.com/pborman/uuid/uuid.go +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -8,9 +8,9 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "fmt" "io" - "strings" + + guuid "github.com/google/uuid" ) // Array is a pass-by-value UUID that can be used as an effecient key in a map. @@ -24,7 +24,7 @@ func (uuid Array) UUID() UUID { // String returns the string representation of uuid, // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. func (uuid Array) String() string { - return uuid.UUID().String() + return guuid.UUID(uuid).String() } // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -32,18 +32,18 @@ func (uuid Array) String() string { type UUID []byte // A Version represents a UUIDs version. -type Version byte +type Version = guuid.Version // A Variant represents a UUIDs variant. -type Variant byte +type Variant = guuid.Variant // Constants returned by Variant. const ( - Invalid = Variant(iota) // Invalid UUID - RFC4122 // The variant specified in RFC4122 - Reserved // Reserved, NCS backward compatibility. - Microsoft // Reserved, Microsoft Corporation backward compatibility. - Future // Reserved for future definition. + Invalid = guuid.Invalid // Invalid UUID + RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 + Reserved = guuid.Reserved // Reserved, NCS backward compatibility. + Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future = guuid.Future // Reserved for future definition. ) var rander = rand.Reader // random function @@ -54,35 +54,23 @@ func New() string { return NewRandom().String() } -// Parse decodes s into a UUID or returns nil. Both the UUID form of -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for +// the formats parsed. func Parse(s string) UUID { - if len(s) == 36+9 { - if strings.ToLower(s[:9]) != "urn:uuid:" { - return nil - } - s = s[9:] - } else if len(s) != 36 { - return nil + gu, err := guuid.Parse(s) + if err == nil { + return gu[:] } - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return nil + return nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + gu, err := guuid.ParseBytes(b) + if err == nil { + return gu[:], nil } - var uuid [16]byte - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(s[x:]); !ok { - return nil - } else { - uuid[i] = v - } - } - return uuid[:] + return nil, err } // Equal returns true if uuid1 and uuid2 are equal. @@ -163,29 +151,6 @@ func (uuid UUID) Version() (Version, bool) { return Version(uuid[6] >> 4), true } -func (v Version) String() string { - if v > 15 { - return fmt.Sprintf("BAD_VERSION_%d", v) - } - return fmt.Sprintf("VERSION_%d", v) -} - -func (v Variant) String() string { - switch v { - case RFC4122: - return "RFC4122" - case Reserved: - return "Reserved" - case Microsoft: - return "Microsoft" - case Future: - return "Future" - case Invalid: - return "Invalid" - } - return fmt.Sprintf("BadVariant%d", int(v)) -} - // SetRand sets the random number generator to r, which implements io.Reader. // If r.Read returns an error when the package requests random data then // a panic will be issued. @@ -193,9 +158,5 @@ func (v Variant) String() string { // Calling SetRand with nil sets the random number generator to the default // generator. func SetRand(r io.Reader) { - if r == nil { - rander = rand.Reader - return - } - rander = r + guuid.SetRand(r) } diff --git a/vendor/github.com/pborman/uuid/version1.go b/vendor/github.com/pborman/uuid/version1.go index 0127eacfa..7af948da7 100644 --- a/vendor/github.com/pborman/uuid/version1.go +++ b/vendor/github.com/pborman/uuid/version1.go @@ -5,7 +5,7 @@ package uuid import ( - "encoding/binary" + guuid "github.com/google/uuid" ) // NewUUID returns a Version 1 UUID based on the current NodeID and clock @@ -15,27 +15,9 @@ import ( // SetClockSequence then it will be set automatically. If GetTime fails to // return the current NewUUID returns nil. func NewUUID() UUID { - if nodeID == nil { - SetNodeInterface("") + gu, err := guuid.NewUUID() + if err == nil { + return UUID(gu[:]) } - - now, seq, err := GetTime() - if err != nil { - return nil - } - - uuid := make([]byte, 16) - - time_low := uint32(now & 0xffffffff) - time_mid := uint16((now >> 32) & 0xffff) - time_hi := uint16((now >> 48) & 0x0fff) - time_hi |= 0x1000 // Version 1 - - binary.BigEndian.PutUint32(uuid[0:], time_low) - binary.BigEndian.PutUint16(uuid[4:], time_mid) - binary.BigEndian.PutUint16(uuid[6:], time_hi) - binary.BigEndian.PutUint16(uuid[8:], seq) - copy(uuid[10:], nodeID) - - return uuid + return nil } diff --git a/vendor/github.com/pborman/uuid/version4.go b/vendor/github.com/pborman/uuid/version4.go index b3d4a368d..b459d46d1 100644 --- a/vendor/github.com/pborman/uuid/version4.go +++ b/vendor/github.com/pborman/uuid/version4.go @@ -4,12 +4,14 @@ package uuid +import guuid "github.com/google/uuid" + // Random returns a Random (Version 4) UUID or panics. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. // -// A note about uniqueness derived from from the UUID Wikipedia entry: +// A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being // hit by a meteorite is estimated to be one chance in 17 billion, that @@ -17,9 +19,8 @@ package uuid // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() UUID { - uuid := make([]byte, 16) - randomBits([]byte(uuid)) - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid + if gu, err := guuid.NewRandom(); err == nil { + return UUID(gu[:]) + } + return nil } diff --git a/vendor/github.com/prometheus/prometheus/NOTICE b/vendor/github.com/prometheus/prometheus/NOTICE deleted file mode 100644 index 47de2415e..000000000 --- a/vendor/github.com/prometheus/prometheus/NOTICE +++ /dev/null @@ -1,87 +0,0 @@ -The Prometheus systems and service monitoring server -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - - -The following components are included in this product: - -Bootstrap -http://getbootstrap.com -Copyright 2011-2014 Twitter, Inc. -Licensed under the MIT License - -bootstrap3-typeahead.js -https://github.com/bassjobsen/Bootstrap-3-Typeahead -Original written by @mdo and @fat -Copyright 2014 Bass Jobsen @bassjobsen -Licensed under the Apache License, Version 2.0 - -fuzzy -https://github.com/mattyork/fuzzy -Original written by @mattyork -Copyright 2012 Matt York -Licensed under the MIT License - -bootstrap-datetimepicker.js -https://github.com/Eonasdan/bootstrap-datetimepicker -Copyright 2015 Jonathan Peterson (@Eonasdan) -Licensed under the MIT License - -moment.js -https://github.com/moment/moment/ -Copyright JS Foundation and other contributors -Licensed under the MIT License - -Rickshaw -https://github.com/shutterstock/rickshaw -Copyright 2011-2014 by Shutterstock Images, LLC -See https://github.com/shutterstock/rickshaw/blob/master/LICENSE for license details - -mustache.js -https://github.com/janl/mustache.js -Copyright 2009 Chris Wanstrath (Ruby) -Copyright 2010-2014 Jan Lehnardt (JavaScript) -Copyright 2010-2015 The mustache.js community -Licensed under the MIT License - -jQuery -https://jquery.org -Copyright jQuery Foundation and other contributors -Licensed under the MIT License - -Go support for Protocol Buffers - Google's data interchange format -http://github.com/golang/protobuf/ -Copyright 2010 The Go Authors -See source code for license details. - -Go support for leveled logs, analogous to -https://code.google.com/p/google-glog/ -Copyright 2013 Google Inc. -Licensed under the Apache License, Version 2.0 - -Support for streaming Protocol Buffer messages for the Go language (golang). -https://github.com/matttproud/golang_protobuf_extensions -Copyright 2013 Matt T. Proud -Licensed under the Apache License, Version 2.0 - -DNS library in Go -http://miek.nl/posts/2014/Aug/16/go-dns-package/ -Copyright 2009 The Go Authors, 2011 Miek Gieben -See https://github.com/miekg/dns/blob/master/LICENSE for license details. - -LevelDB key/value database in Go -https://github.com/syndtr/goleveldb -Copyright 2012 Suryandaru Triandana -See https://github.com/syndtr/goleveldb/blob/master/LICENSE for license details. - -gosnappy - a fork of code.google.com/p/snappy-go -https://github.com/syndtr/gosnappy -Copyright 2011 The Snappy-Go Authors -See https://github.com/syndtr/gosnappy/blob/master/LICENSE for license details. - -go-zookeeper - Native ZooKeeper client for Go -https://github.com/samuel/go-zookeeper -Copyright (c) 2013, Samuel Stauffer -See https://github.com/samuel/go-zookeeper/blob/master/LICENSE for license details. diff --git a/vendor/github.com/prometheus/prometheus/LICENSE b/vendor/github.com/prometheus/tsdb/LICENSE similarity index 100% rename from vendor/github.com/prometheus/prometheus/LICENSE rename to vendor/github.com/prometheus/tsdb/LICENSE diff --git a/vendor/github.com/prometheus/tsdb/fileutil/dir_unix.go b/vendor/github.com/prometheus/tsdb/fileutil/dir_unix.go new file mode 100644 index 000000000..58a77dfc1 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/dir_unix.go @@ -0,0 +1,22 @@ +// Copyright 2016 The etcd Authors +// +// 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. + +// +build !windows + +package fileutil + +import "os" + +// OpenDir opens a directory for syncing. +func OpenDir(path string) (*os.File, error) { return os.Open(path) } diff --git a/vendor/github.com/prometheus/tsdb/fileutil/dir_windows.go b/vendor/github.com/prometheus/tsdb/fileutil/dir_windows.go new file mode 100644 index 000000000..c123395c0 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/dir_windows.go @@ -0,0 +1,46 @@ +// Copyright 2016 The etcd Authors +// +// 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. + +// +build windows + +package fileutil + +import ( + "os" + "syscall" +) + +// OpenDir opens a directory in windows with write access for syncing. +func OpenDir(path string) (*os.File, error) { + fd, err := openDir(path) + if err != nil { + return nil, err + } + return os.NewFile(uintptr(fd), path), nil +} + +func openDir(path string) (fd syscall.Handle, err error) { + if len(path) == 0 { + return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return syscall.InvalidHandle, err + } + access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE) + sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE) + createmode := uint32(syscall.OPEN_EXISTING) + fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) + return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0) +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go b/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go new file mode 100644 index 000000000..4088f522a --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/fileutil.go @@ -0,0 +1,159 @@ +// Copyright 2018 The Prometheus Authors +// 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. + +// Package fileutil provides utility methods used when dealing with the filesystem in tsdb. +// It is largely copied from github.com/coreos/etcd/pkg/fileutil to avoid the +// dependency chain it brings with it. +// Please check github.com/coreos/etcd for licensing information. +package fileutil + +import ( + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" +) + +// CopyDirs copies all directories, subdirectories and files recursively including the empty folders. +// Source and destination must be full paths. +func CopyDirs(src, dest string) error { + if err := os.MkdirAll(dest, 0777); err != nil { + return err + } + files, err := readDirs(src) + if err != nil { + return err + } + + for _, f := range files { + dp := filepath.Join(dest, f) + sp := filepath.Join(src, f) + + stat, err := os.Stat(sp) + if err != nil { + return err + } + + // Empty directories are also created. + if stat.IsDir() { + if err := os.MkdirAll(dp, 0777); err != nil { + return err + } + continue + } + + if err := copyFile(sp, dp); err != nil { + return err + } + } + return nil +} + +func copyFile(src, dest string) error { + data, err := ioutil.ReadFile(src) + if err != nil { + return err + } + + err = ioutil.WriteFile(dest, data, 0644) + if err != nil { + return err + } + return nil +} + +// readDirs reads the source directory recursively and +// returns relative paths to all files and empty directories. +func readDirs(src string) ([]string, error) { + var files []string + + err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error { + relativePath := strings.TrimPrefix(path, src) + if len(relativePath) > 0 { + files = append(files, relativePath) + } + return nil + }) + if err != nil { + return nil, err + } + return files, nil +} + +// ReadDir returns the filenames in the given directory in sorted order. +func ReadDir(dirpath string) ([]string, error) { + dir, err := os.Open(dirpath) + if err != nil { + return nil, err + } + defer dir.Close() + names, err := dir.Readdirnames(-1) + if err != nil { + return nil, err + } + sort.Strings(names) + return names, nil +} + +// Rename safely renames a file. +func Rename(from, to string) error { + if err := os.Rename(from, to); err != nil { + return err + } + + // Directory was renamed; sync parent dir to persist rename. + pdir, err := OpenDir(filepath.Dir(to)) + if err != nil { + return err + } + + if err = pdir.Sync(); err != nil { + pdir.Close() + return err + } + return pdir.Close() +} + +// Replace moves a file or directory to a new location and deletes any previous data. +// It is not atomic. +func Replace(from, to string) error { + // Remove destination only if it is a dir otherwise leave it to os.Rename + // as it replaces the destination file and is atomic. + { + f, err := os.Stat(to) + if !os.IsNotExist(err) { + if err == nil && f.IsDir() { + if err := os.RemoveAll(to); err != nil { + return err + } + } + } + } + + if err := os.Rename(from, to); err != nil { + return err + } + + // Directory was renamed; sync parent dir to persist rename. + pdir, err := OpenDir(filepath.Dir(to)) + if err != nil { + return err + } + + if err = pdir.Sync(); err != nil { + pdir.Close() + return err + } + return pdir.Close() +} diff --git a/vendor/github.com/prometheus/prometheus/util/flock/flock.go b/vendor/github.com/prometheus/tsdb/fileutil/flock.go similarity index 68% rename from vendor/github.com/prometheus/prometheus/util/flock/flock.go rename to vendor/github.com/prometheus/tsdb/fileutil/flock.go index 5dc22a2fa..d5eaa7ca2 100644 --- a/vendor/github.com/prometheus/prometheus/util/flock/flock.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/flock.go @@ -11,12 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package flock provides portable file locking. It is essentially ripped out -// from the code of github.com/syndtr/goleveldb. Strange enough that the -// standard library does not provide this functionality. Once this package has -// proven to work as expected, we should probably turn it into a separate -// general purpose package for humanity. -package flock +package fileutil import ( "os" @@ -28,19 +23,19 @@ type Releaser interface { Release() error } -// New locks the file with the provided name. If the file does not exist, it is +// Flock locks the file with the provided name. If the file does not exist, it is // created. The returned Releaser is used to release the lock. existed is true // if the file to lock already existed. A non-nil error is returned if the // locking has failed. Neither this function nor the returned Releaser is // goroutine-safe. -func New(fileName string) (r Releaser, existed bool, err error) { +func Flock(fileName string) (r Releaser, existed bool, err error) { if err = os.MkdirAll(filepath.Dir(fileName), 0755); err != nil { - return + return nil, false, err } _, err = os.Stat(fileName) existed = err == nil r, err = newLock(fileName) - return + return r, existed, err } diff --git a/vendor/github.com/prometheus/prometheus/util/flock/flock_plan9.go b/vendor/github.com/prometheus/tsdb/fileutil/flock_plan9.go similarity index 98% rename from vendor/github.com/prometheus/prometheus/util/flock/flock_plan9.go rename to vendor/github.com/prometheus/tsdb/fileutil/flock_plan9.go index 004e85c0f..8a3d44c5e 100644 --- a/vendor/github.com/prometheus/prometheus/util/flock/flock_plan9.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/flock_plan9.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package flock +package fileutil import "os" diff --git a/vendor/github.com/prometheus/prometheus/util/flock/flock_solaris.go b/vendor/github.com/prometheus/tsdb/fileutil/flock_solaris.go similarity index 98% rename from vendor/github.com/prometheus/prometheus/util/flock/flock_solaris.go rename to vendor/github.com/prometheus/tsdb/fileutil/flock_solaris.go index 299fc8744..7f527ae6c 100644 --- a/vendor/github.com/prometheus/prometheus/util/flock/flock_solaris.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/flock_solaris.go @@ -13,7 +13,7 @@ // +build solaris -package flock +package fileutil import ( "os" diff --git a/vendor/github.com/prometheus/prometheus/util/flock/flock_unix.go b/vendor/github.com/prometheus/tsdb/fileutil/flock_unix.go similarity index 98% rename from vendor/github.com/prometheus/prometheus/util/flock/flock_unix.go rename to vendor/github.com/prometheus/tsdb/fileutil/flock_unix.go index 7d71f8fc0..f493fbd83 100644 --- a/vendor/github.com/prometheus/prometheus/util/flock/flock_unix.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/flock_unix.go @@ -13,7 +13,7 @@ // +build darwin dragonfly freebsd linux netbsd openbsd -package flock +package fileutil import ( "os" diff --git a/vendor/github.com/prometheus/prometheus/util/flock/flock_windows.go b/vendor/github.com/prometheus/tsdb/fileutil/flock_windows.go similarity index 98% rename from vendor/github.com/prometheus/prometheus/util/flock/flock_windows.go rename to vendor/github.com/prometheus/tsdb/fileutil/flock_windows.go index bf7266f14..1c17ff4ea 100644 --- a/vendor/github.com/prometheus/prometheus/util/flock/flock_windows.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/flock_windows.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package flock +package fileutil import "syscall" diff --git a/vendor/github.com/prometheus/tsdb/fileutil/mmap.go b/vendor/github.com/prometheus/tsdb/fileutil/mmap.go new file mode 100644 index 000000000..26fc80c58 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/mmap.go @@ -0,0 +1,61 @@ +// Copyright 2018 The Prometheus Authors +// 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. + +package fileutil + +import ( + "os" + + "github.com/pkg/errors" +) + +type MmapFile struct { + f *os.File + b []byte +} + +func OpenMmapFile(path string) (*MmapFile, error) { + f, err := os.Open(path) + if err != nil { + return nil, errors.Wrap(err, "try lock file") + } + info, err := f.Stat() + if err != nil { + return nil, errors.Wrap(err, "stat") + } + + b, err := mmap(f, int(info.Size())) + if err != nil { + return nil, errors.Wrap(err, "mmap") + } + + return &MmapFile{f: f, b: b}, nil +} + +func (f *MmapFile) Close() error { + err0 := munmap(f.b) + err1 := f.f.Close() + + if err0 != nil { + return err0 + } + return err1 +} + +func (f *MmapFile) File() *os.File { + return f.f +} + +func (f *MmapFile) Bytes() []byte { + return f.b +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/mmap_386.go b/vendor/github.com/prometheus/tsdb/fileutil/mmap_386.go new file mode 100644 index 000000000..66b9d3680 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/mmap_386.go @@ -0,0 +1,18 @@ +// Copyright 2018 The Prometheus Authors +// 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. + +// +build windows + +package fileutil + +const maxMapSize = 0x7FFFFFFF // 2GB diff --git a/vendor/github.com/prometheus/tsdb/fileutil/mmap_amd64.go b/vendor/github.com/prometheus/tsdb/fileutil/mmap_amd64.go new file mode 100644 index 000000000..4b523bc67 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/mmap_amd64.go @@ -0,0 +1,18 @@ +// Copyright 2018 The Prometheus Authors +// 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. + +// +build windows + +package fileutil + +const maxMapSize = 0xFFFFFFFFFFFF // 256TB diff --git a/vendor/github.com/prometheus/tsdb/fileutil/mmap_unix.go b/vendor/github.com/prometheus/tsdb/fileutil/mmap_unix.go new file mode 100644 index 000000000..043f4d408 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/mmap_unix.go @@ -0,0 +1,30 @@ +// Copyright 2017 The Prometheus Authors +// 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. + +// +build !windows,!plan9 + +package fileutil + +import ( + "os" + + "golang.org/x/sys/unix" +) + +func mmap(f *os.File, length int) ([]byte, error) { + return unix.Mmap(int(f.Fd()), 0, length, unix.PROT_READ, unix.MAP_SHARED) +} + +func munmap(b []byte) (err error) { + return unix.Munmap(b) +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/mmap_windows.go b/vendor/github.com/prometheus/tsdb/fileutil/mmap_windows.go new file mode 100644 index 000000000..b94226412 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/mmap_windows.go @@ -0,0 +1,46 @@ +// Copyright 2017 The Prometheus Authors +// 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. + +package fileutil + +import ( + "os" + "syscall" + "unsafe" +) + +func mmap(f *os.File, size int) ([]byte, error) { + low, high := uint32(size), uint32(size>>32) + h, errno := syscall.CreateFileMapping(syscall.Handle(f.Fd()), nil, syscall.PAGE_READONLY, high, low, nil) + if h == 0 { + return nil, os.NewSyscallError("CreateFileMapping", errno) + } + + addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(size)) + if addr == 0 { + return nil, os.NewSyscallError("MapViewOfFile", errno) + } + + if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { + return nil, os.NewSyscallError("CloseHandle", err) + } + + return (*[maxMapSize]byte)(unsafe.Pointer(addr))[:size], nil +} + +func munmap(b []byte) error { + if err := syscall.UnmapViewOfFile((uintptr)(unsafe.Pointer(&b[0]))); err != nil { + return os.NewSyscallError("UnmapViewOfFile", err) + } + return nil +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/preallocate.go b/vendor/github.com/prometheus/tsdb/fileutil/preallocate.go new file mode 100644 index 000000000..c747b7cf8 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/preallocate.go @@ -0,0 +1,54 @@ +// Copyright 2015 The etcd Authors +// +// 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. + +package fileutil + +import ( + "io" + "os" +) + +// Preallocate tries to allocate the space for given +// file. This operation is only supported on linux by a +// few filesystems (btrfs, ext4, etc.). +// If the operation is unsupported, no error will be returned. +// Otherwise, the error encountered will be returned. +func Preallocate(f *os.File, sizeInBytes int64, extendFile bool) error { + if sizeInBytes == 0 { + // fallocate will return EINVAL if length is 0; skip + return nil + } + if extendFile { + return preallocExtend(f, sizeInBytes) + } + return preallocFixed(f, sizeInBytes) +} + +func preallocExtendTrunc(f *os.File, sizeInBytes int64) error { + curOff, err := f.Seek(0, io.SeekCurrent) + if err != nil { + return err + } + size, err := f.Seek(sizeInBytes, io.SeekEnd) + if err != nil { + return err + } + if _, err = f.Seek(curOff, io.SeekStart); err != nil { + return err + } + if sizeInBytes > size { + return nil + } + return f.Truncate(sizeInBytes) +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/preallocate_darwin.go b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_darwin.go new file mode 100644 index 000000000..c9fa1a6c2 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_darwin.go @@ -0,0 +1,41 @@ +// Copyright 2015 The etcd Authors +// +// 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. + +package fileutil + +import ( + "os" + "syscall" + "unsafe" +) + +func preallocExtend(f *os.File, sizeInBytes int64) error { + if err := preallocFixed(f, sizeInBytes); err != nil { + return err + } + return preallocExtendTrunc(f, sizeInBytes) +} + +func preallocFixed(f *os.File, sizeInBytes int64) error { + fstore := &syscall.Fstore_t{ + Flags: syscall.F_ALLOCATEALL, + Posmode: syscall.F_PEOFPOSMODE, + Length: sizeInBytes} + p := unsafe.Pointer(fstore) + _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_PREALLOCATE), uintptr(p)) + if errno == 0 || errno == syscall.ENOTSUP { + return nil + } + return errno +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/preallocate_linux.go b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_linux.go new file mode 100644 index 000000000..ada046221 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_linux.go @@ -0,0 +1,47 @@ +// Copyright 2015 The etcd Authors +// +// 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. + +package fileutil + +import ( + "os" + "syscall" +) + +func preallocExtend(f *os.File, sizeInBytes int64) error { + // use mode = 0 to change size + err := syscall.Fallocate(int(f.Fd()), 0, 0, sizeInBytes) + if err != nil { + errno, ok := err.(syscall.Errno) + // not supported; fallback + // fallocate EINTRs frequently in some environments; fallback + if ok && (errno == syscall.ENOTSUP || errno == syscall.EINTR) { + return preallocExtendTrunc(f, sizeInBytes) + } + } + return err +} + +func preallocFixed(f *os.File, sizeInBytes int64) error { + // use mode = 1 to keep size; see FALLOC_FL_KEEP_SIZE + err := syscall.Fallocate(int(f.Fd()), 1, 0, sizeInBytes) + if err != nil { + errno, ok := err.(syscall.Errno) + // treat not supported as nil error + if ok && errno == syscall.ENOTSUP { + return nil + } + } + return err +} diff --git a/vendor/github.com/minio/sha256-simd/cpuid_others_arm64.go b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_other.go similarity index 60% rename from vendor/github.com/minio/sha256-simd/cpuid_others_arm64.go rename to vendor/github.com/prometheus/tsdb/fileutil/preallocate_other.go index 0fb4022f7..162fbc5f7 100644 --- a/vendor/github.com/minio/sha256-simd/cpuid_others_arm64.go +++ b/vendor/github.com/prometheus/tsdb/fileutil/preallocate_other.go @@ -1,6 +1,4 @@ -// +build arm64,!linux - -// Minio Cloud Storage, (C) 2016 Minio, Inc. +// Copyright 2015 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,23 +11,15 @@ // 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. -// -package sha256 +// +build !linux,!darwin -func cpuid(op uint32) (eax, ebx, ecx, edx uint32) { - return 0, 0, 0, 0 +package fileutil + +import "os" + +func preallocExtend(f *os.File, sizeInBytes int64) error { + return preallocExtendTrunc(f, sizeInBytes) } -func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) { - return 0, 0, 0, 0 -} - -func xgetbv(index uint32) (eax, edx uint32) { - return 0, 0 -} - -// Check for sha2 instruction flag. -func haveArmSha() bool { - return false -} +func preallocFixed(f *os.File, sizeInBytes int64) error { return nil } diff --git a/vendor/github.com/prometheus/tsdb/fileutil/sync.go b/vendor/github.com/prometheus/tsdb/fileutil/sync.go new file mode 100644 index 000000000..2e64a4088 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/sync.go @@ -0,0 +1,24 @@ +// Copyright 2016 The etcd Authors +// +// 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. + +// +build !linux,!darwin + +package fileutil + +import "os" + +// Fdatasync is a wrapper around file.Sync(). Special handling is needed on linux platform. +func Fdatasync(f *os.File) error { + return f.Sync() +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/sync_darwin.go b/vendor/github.com/prometheus/tsdb/fileutil/sync_darwin.go new file mode 100644 index 000000000..2af1b0f41 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/sync_darwin.go @@ -0,0 +1,27 @@ +// Copyright 2016 The etcd Authors +// +// 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. + +// +build darwin + +package fileutil + +import ( + "os" +) + +// Fdatasync on darwin platform invokes fcntl(F_FULLFSYNC) for actual persistence +// on physical drive media. +func Fdatasync(f *os.File) error { + return f.Sync() +} diff --git a/vendor/github.com/prometheus/tsdb/fileutil/sync_linux.go b/vendor/github.com/prometheus/tsdb/fileutil/sync_linux.go new file mode 100644 index 000000000..8b4fc8268 --- /dev/null +++ b/vendor/github.com/prometheus/tsdb/fileutil/sync_linux.go @@ -0,0 +1,29 @@ +// Copyright 2016 The etcd Authors +// +// 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. + +// +build linux + +package fileutil + +import ( + "os" + "syscall" +) + +// Fdatasync is similar to fsync(), but does not flush modified metadata +// unless that metadata is needed in order to allow a subsequent data retrieval +// to be correctly handled. +func Fdatasync(f *os.File) error { + return syscall.Fdatasync(int(f.Fd())) +} diff --git a/vendor/github.com/spacemonkeygo/openssl/go.mod b/vendor/github.com/spacemonkeygo/openssl/go.mod deleted file mode 100644 index 73f3bbfe5..000000000 --- a/vendor/github.com/spacemonkeygo/openssl/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/spacemonkeygo/openssl - -require github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 diff --git a/vendor/github.com/status-im/keycard-go/LICENSE.md b/vendor/github.com/status-im/keycard-go/LICENSE.md new file mode 100644 index 000000000..3759302a4 --- /dev/null +++ b/vendor/github.com/status-im/keycard-go/LICENSE.md @@ -0,0 +1,356 @@ +Mozilla Public License Version 2.0 +================================== + +### 1. Definitions + +**1.1. “Contributor”** + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +**1.2. “Contributor Version”** + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +**1.3. “Contribution”** + means Covered Software of a particular Contributor. + +**1.4. “Covered Software”** + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +**1.5. “Incompatible With Secondary Licenses”** + means + +* **(a)** that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or +* **(b)** that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +**1.6. “Executable Form”** + means any form of the work other than Source Code Form. + +**1.7. “Larger Work”** + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +**1.8. “License”** + means this document. + +**1.9. “Licensable”** + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +**1.10. “Modifications”** + means any of the following: + +* **(a)** any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or +* **(b)** any new file in Source Code Form that contains any Covered + Software. + +**1.11. “Patent Claims” of a Contributor** + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +**1.12. “Secondary License”** + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +**1.13. “Source Code Form”** + means the form of the work preferred for making modifications. + +**1.14. “You” (or “Your”)** + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, “control” means **(a)** the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or **(b)** ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + + +### 2. License Grants and Conditions + +#### 2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +* **(a)** under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and +* **(b)** under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +#### 2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +#### 2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +* **(a)** for any code that a Contributor has removed from Covered Software; + or +* **(b)** for infringements caused by: **(i)** Your and any other third party's + modifications of Covered Software, or **(ii)** the combination of its + Contributions with other software (except as part of its Contributor + Version); or +* **(c)** under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +#### 2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +#### 2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +#### 2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +#### 2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + + +### 3. Responsibilities + +#### 3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +#### 3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +* **(a)** such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +* **(b)** You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +#### 3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +#### 3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +#### 3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + + +### 4. Inability to Comply Due to Statute or Regulation + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: **(a)** comply with +the terms of this License to the maximum extent possible; and **(b)** +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + + +### 5. Termination + +**5.1.** The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated **(a)** provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and **(b)** on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +**5.2.** If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +**5.3.** In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + + +### 6. Disclaimer of Warranty + +> Covered Software is provided under this License on an “as is” +> basis, without warranty of any kind, either expressed, implied, or +> statutory, including, without limitation, warranties that the +> Covered Software is free of defects, merchantable, fit for a +> particular purpose or non-infringing. The entire risk as to the +> quality and performance of the Covered Software is with You. +> Should any Covered Software prove defective in any respect, You +> (not any Contributor) assume the cost of any necessary servicing, +> repair, or correction. This disclaimer of warranty constitutes an +> essential part of this License. No use of any Covered Software is +> authorized under this License except under this disclaimer. + +### 7. Limitation of Liability + +> Under no circumstances and under no legal theory, whether tort +> (including negligence), contract, or otherwise, shall any +> Contributor, or anyone who distributes Covered Software as +> permitted above, be liable to You for any direct, indirect, +> special, incidental, or consequential damages of any character +> including, without limitation, damages for lost profits, loss of +> goodwill, work stoppage, computer failure or malfunction, or any +> and all other commercial damages or losses, even if such party +> shall have been informed of the possibility of such damages. This +> limitation of liability shall not apply to liability for death or +> personal injury resulting from such party's negligence to the +> extent applicable law prohibits such limitation. Some +> jurisdictions do not allow the exclusion or limitation of +> incidental or consequential damages, so this exclusion and +> limitation may not apply to You. + + +### 8. Litigation + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + + +### 9. Miscellaneous + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + + +### 10. Versions of the License + +#### 10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +#### 10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +#### 10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +#### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +## Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +## Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/status-im/keycard-go/derivationpath/decoder.go b/vendor/github.com/status-im/keycard-go/derivationpath/decoder.go new file mode 100644 index 000000000..f269da258 --- /dev/null +++ b/vendor/github.com/status-im/keycard-go/derivationpath/decoder.go @@ -0,0 +1,214 @@ +package derivationpath + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +type StartingPoint int + +const ( + tokenMaster = 0x6D // char m + tokenSeparator = 0x2F // char / + tokenHardened = 0x27 // char ' + tokenDot = 0x2E // char . + + hardenedStart = 0x80000000 // 2^31 +) + +const ( + StartingPointMaster StartingPoint = iota + 1 + StartingPointCurrent + StartingPointParent +) + +type parseFunc = func() error + +type decoder struct { + r *strings.Reader + f parseFunc + pos int + path []uint32 + start StartingPoint + currentToken string + currentTokenHardened bool +} + +func newDecoder(path string) *decoder { + d := &decoder{ + r: strings.NewReader(path), + } + + d.reset() + + return d +} + +func (d *decoder) reset() { + d.r.Seek(0, io.SeekStart) + d.pos = 0 + d.start = StartingPointCurrent + d.f = d.parseStart + d.path = make([]uint32, 0) + d.resetCurrentToken() +} + +func (d *decoder) resetCurrentToken() { + d.currentToken = "" + d.currentTokenHardened = false +} + +func (d *decoder) parse() (StartingPoint, []uint32, error) { + for { + err := d.f() + if err != nil { + if err == io.EOF { + err = nil + } else { + err = fmt.Errorf("at position %d, %s", d.pos, err.Error()) + } + + return d.start, d.path, err + } + } + + return d.start, d.path, nil +} + +func (d *decoder) readByte() (byte, error) { + b, err := d.r.ReadByte() + if err != nil { + return b, err + } + + d.pos++ + + return b, nil +} + +func (d *decoder) unreadByte() error { + err := d.r.UnreadByte() + if err != nil { + return err + } + + d.pos-- + + return nil +} + +func (d *decoder) parseStart() error { + b, err := d.readByte() + if err != nil { + return err + } + + if b == tokenMaster { + d.start = StartingPointMaster + d.f = d.parseSeparator + return nil + } + + if b == tokenDot { + b2, err := d.readByte() + if err != nil { + return err + } + + if b2 == tokenDot { + d.f = d.parseSeparator + d.start = StartingPointParent + return nil + } + + d.f = d.parseSeparator + d.start = StartingPointCurrent + return d.unreadByte() + } + + d.f = d.parseSegment + + return d.unreadByte() +} + +func (d *decoder) saveSegment() error { + if len(d.currentToken) > 0 { + i, err := strconv.ParseUint(d.currentToken, 10, 32) + if err != nil { + return err + } + + if i >= hardenedStart { + d.pos -= len(d.currentToken) - 1 + return fmt.Errorf("index must be lower than 2^31, got %d", i) + } + + if d.currentTokenHardened { + i += hardenedStart + } + + d.path = append(d.path, uint32(i)) + } + + d.f = d.parseSegment + d.resetCurrentToken() + + return nil +} + +func (d *decoder) parseSeparator() error { + b, err := d.readByte() + if err != nil { + return err + } + + if b == tokenSeparator { + return d.saveSegment() + } + + return fmt.Errorf("expected %s, got %s", string(tokenSeparator), string(b)) +} + +func (d *decoder) parseSegment() error { + b, err := d.readByte() + if err == io.EOF { + if len(d.currentToken) == 0 { + return fmt.Errorf("expected number, got EOF") + } + + if newErr := d.saveSegment(); newErr != nil { + return newErr + } + + return err + } + + if err != nil { + return err + } + + if len(d.currentToken) > 0 && b == tokenSeparator { + return d.saveSegment() + } + + if len(d.currentToken) > 0 && b == tokenHardened { + d.currentTokenHardened = true + d.f = d.parseSeparator + return nil + } + + if b < 0x30 || b > 0x39 { + return fmt.Errorf("expected number, got %s", string(b)) + } + + d.currentToken = fmt.Sprintf("%s%s", d.currentToken, string(b)) + + return nil +} + +func Decode(str string) (StartingPoint, []uint32, error) { + d := newDecoder(str) + return d.parse() +} diff --git a/vendor/github.com/status-im/keycard-go/derivationpath/encoder.go b/vendor/github.com/status-im/keycard-go/derivationpath/encoder.go new file mode 100644 index 000000000..c1f5b0239 --- /dev/null +++ b/vendor/github.com/status-im/keycard-go/derivationpath/encoder.go @@ -0,0 +1,36 @@ +package derivationpath + +import ( + "bytes" + "encoding/binary" + "fmt" + "strings" +) + +func Encode(rawPath []uint32) string { + segments := []string{string(tokenMaster)} + + for _, i := range rawPath { + suffix := "" + + if i >= hardenedStart { + i = i - hardenedStart + suffix = string(tokenHardened) + } + + segments = append(segments, fmt.Sprintf("%d%s", i, suffix)) + } + + return strings.Join(segments, string(tokenSeparator)) +} + +func EncodeFromBytes(data []byte) (string, error) { + buf := bytes.NewBuffer(data) + rawPath := make([]uint32, buf.Len()/4) + err := binary.Read(buf, binary.BigEndian, &rawPath) + if err != nil { + return "", err + } + + return Encode(rawPath), nil +} diff --git a/vendor/github.com/steakknife/bloomfilter/.travis.yml b/vendor/github.com/steakknife/bloomfilter/.travis.yml new file mode 100644 index 000000000..73d1238c5 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/.travis.yml @@ -0,0 +1,14 @@ +language: go +dist: trusty +sudo: false +go: + - "1.8.x" + - "1.9.x" + - "1.10.x" + - master +before_script: + - "go get -u gopkg.in/alecthomas/gometalinter.v2" + - "gometalinter.v2 --install" +script: + - "go test -v -cover -benchmem -bench=. $(go list ./... | grep -v /vendor/ | sed \"s&_${PWD}&.&\")" + - "gometalinter.v2 --enable-all ./..." diff --git a/vendor/github.com/steakknife/bloomfilter/MIT-LICENSE.txt b/vendor/github.com/steakknife/bloomfilter/MIT-LICENSE.txt new file mode 100644 index 000000000..ccf77fe46 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/MIT-LICENSE.txt @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright © 2014, 2015 Barry Allard + +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/steakknife/bloomfilter/README.md b/vendor/github.com/steakknife/bloomfilter/README.md new file mode 100644 index 000000000..4587f143a --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/README.md @@ -0,0 +1,123 @@ +**Important**: Zeroth, [consider](https://bdupras.github.io/filter-tutorial/) if a [Cuckoo filter](https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf) could be [right for your use-case](https://github.com/seiflotfy/cuckoofilter). + + +[![GoDoc](https://godoc.org/github.com/steakknife/bloomfilter?status.png)](https://godoc.org/github.com/steakknife/bloomfilter) [![travis](https://img.shields.io/travis/steakknife/bloomfilter.svg)](https://travis-ci.org/steakknife/bloomfilter) + +# Face-meltingly fast, thread-safe, marshalable, unionable, probability- and optimal-size-calculating Bloom filter in go + +Copyright © 2014-2016,2018 Barry Allard + +[MIT license](MIT-LICENSE.txt) + +## WTF is a bloom filter + +**TL;DR: **Probabilistic, extra lookup table to track a set of elements kept elsewhere to reduce expensive, unnecessary set element retrieval and/or iterator operations **when an element is not present in the set.** It's a classic time-storage tradeoff algoritm. + +### Properties + +#### [See wikipedia](https://en.wikipedia.org/wiki/Bloom_filter) for algorithm details + +|Impact|What|Description| +|---|---|---| +|Good|No false negatives|know for certain if a given element is definitely NOT in the set| +|Bad|False positives|uncertain if a given element is in the set| +|Bad|Theoretical potential for hash collisions|in very large systems and/or badly hash.Hash64-conforming implementations| +|Bad|Add only|Cannot remove an element, it would destroy information about other elements| +|Good|Constant storage|uses only a fixed amount of memory| + +## Naming conventions + +(Similar to algorithm) + +|Variable/function|Description|Range| +|---|---|---| +|m/M()|number of bits in the bloom filter (memory representation is about m/8 bytes in size)|>=2| +|n/N()|number of elements present|>=0| +|k/K()|number of keys to use (keys are kept private to user code but are de/serialized to Marshal and file I/O)|>=0| +|maxN|maximum capacity of intended structure|>0| +|p|maximum allowed probability of collision (for computing m and k for optimal sizing)|>0..<1| + +- Memory representation should be exactly `24 + 8*(k + (m+63)/64) + unsafe.Sizeof(RWMutex)` bytes. +- Serialized (`BinaryMarshaler`) representation should be exactly `72 + 8*(k + (m+63)/64)` bytes. (Disk format is less due to compression.) + +## Binary serialization format + +All values in Little-endian format + +|Offset|Offset (Hex)|Length (bytes)|Name|Type| +|---|---|---|---|---| +|0|00|8|k|`uint64`| +|8|08|8|n|`uint64`| +|16|10|8|m|`uint64`| +|24|18|k|(keys)|`[k]uint64`| +|24+8*k|...|(m+63)/64|(bloom filter)|`[(m+63)/64]uint64`| +|24+8\*k+8\*((m+63)/64)|...|48|(SHA384 of all previous fields, hashed in order)|`[48]byte`| + +- `bloomfilter.Filter` conforms to `encoding.BinaryMarshaler` and `encoding.BinaryUnmarshaler' + +## Usage + +```go + +import "github.com/steakknife/bloomfilter" + +const ( + maxElements = 100000 + probCollide = 0.0000001 +) + +bf, err := bloomfilter.NewOptimal(maxElements, probCollide) +if err != nil { + panic(err) +} + +someValue := ... // must conform to hash.Hash64 + +bf.Add(someValue) +if bf.Contains(someValue) { // probably true, could be false + // whatever +} + +anotherValue := ... // must also conform to hash.Hash64 + +if bf.Contains(anotherValue) { + panic("This should never happen") +} + +err := bf.WriteFile("1.bf.gz") // saves this BF to a file +if err != nil { + panic(err) +} + +bf2, err := bloomfilter.ReadFile("1.bf.gz") // read the BF to another var +if err != nil { + panic(err) +} +``` + + +## Design + +Where possible, branch-free operations are used to avoid deep pipeline / execution unit stalls on branch-misses. + +## Get + + go get -u github.com/steakknife/bloomfilter # master is always stable + +## Source + +- On the web: [https://github.com/steakknife/bloomfilter](https://github.com/steakknife/bloomfilter) + +- Git: `git clone https://github.com/steakknife/bloomfilter` + +## Contact + +- [Feedback](mailto:barry.allard@gmail.com) + +- [Issues](https://github.com/steakknife/bloomfilter/issues) + +## License + +[MIT license](MIT-LICENSE.txt) + +Copyright © 2014-2016 Barry Allard diff --git a/vendor/github.com/steakknife/bloomfilter/binarymarshaler.go b/vendor/github.com/steakknife/bloomfilter/binarymarshaler.go new file mode 100644 index 000000000..2fa669254 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/binarymarshaler.go @@ -0,0 +1,87 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "bytes" + "crypto/sha512" + "encoding/binary" +) + +// conforms to encoding.BinaryMarshaler + +// marshalled binary layout (Little Endian): +// +// k 1 uint64 +// n 1 uint64 +// m 1 uint64 +// keys [k]uint64 +// bits [(m+63)/64]uint64 +// hash sha384 (384 bits == 48 bytes) +// +// size = (3 + k + (m+63)/64) * 8 bytes +// + +func (f *Filter) marshal() (buf *bytes.Buffer, + hash [sha512.Size384]byte, + err error, +) { + f.lock.RLock() + defer f.lock.RUnlock() + + debug("write bf k=%d n=%d m=%d\n", f.K(), f.n, f.m) + + buf = new(bytes.Buffer) + + err = binary.Write(buf, binary.LittleEndian, f.K()) + if err != nil { + return nil, hash, err + } + + err = binary.Write(buf, binary.LittleEndian, f.n) + if err != nil { + return nil, hash, err + } + + err = binary.Write(buf, binary.LittleEndian, f.m) + if err != nil { + return nil, hash, err + } + + err = binary.Write(buf, binary.LittleEndian, f.keys) + if err != nil { + return nil, hash, err + } + + err = binary.Write(buf, binary.LittleEndian, f.bits) + if err != nil { + return nil, hash, err + } + + hash = sha512.Sum384(buf.Bytes()) + err = binary.Write(buf, binary.LittleEndian, hash) + return buf, hash, err +} + +// MarshalBinary converts a Filter into []bytes +func (f *Filter) MarshalBinary() (data []byte, err error) { + buf, hash, err := f.marshal() + if err != nil { + return nil, err + } + + debug( + "bloomfilter.MarshalBinary: Successfully wrote %d byte(s), sha384 %v", + buf.Len(), hash, + ) + data = buf.Bytes() + return data, nil +} diff --git a/vendor/github.com/steakknife/bloomfilter/binaryunmarshaler.go b/vendor/github.com/steakknife/bloomfilter/binaryunmarshaler.go new file mode 100644 index 000000000..5be1670c5 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/binaryunmarshaler.go @@ -0,0 +1,111 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "bytes" + "crypto/hmac" + "crypto/sha512" + "encoding/binary" + "io" +) + +func unmarshalBinaryHeader(r io.Reader) (k, n, m uint64, err error) { + err = binary.Read(r, binary.LittleEndian, &k) + if err != nil { + return k, n, m, err + } + + if k < KMin { + return k, n, m, errK() + } + + err = binary.Read(r, binary.LittleEndian, &n) + if err != nil { + return k, n, m, err + } + + err = binary.Read(r, binary.LittleEndian, &m) + if err != nil { + return k, n, m, err + } + + if m < MMin { + return k, n, m, errM() + } + + debug("read bf k=%d n=%d m=%d\n", k, n, m) + + return k, n, m, err +} + +func unmarshalBinaryBits(r io.Reader, m uint64) (bits []uint64, err error) { + bits, err = newBits(m) + if err != nil { + return bits, err + } + err = binary.Read(r, binary.LittleEndian, bits) + return bits, err + +} + +func unmarshalBinaryKeys(r io.Reader, k uint64) (keys []uint64, err error) { + keys = make([]uint64, k) + err = binary.Read(r, binary.LittleEndian, keys) + return keys, err +} + +func checkBinaryHash(r io.Reader, data []byte) (err error) { + expectedHash := make([]byte, sha512.Size384) + err = binary.Read(r, binary.LittleEndian, expectedHash) + if err != nil { + return err + } + + actualHash := sha512.Sum384(data[:len(data)-sha512.Size384]) + + if !hmac.Equal(expectedHash, actualHash[:]) { + debug("bloomfilter.UnmarshalBinary() sha384 hash failed:"+ + " actual %v expected %v", actualHash, expectedHash) + return errHash() + } + + debug("bloomfilter.UnmarshalBinary() successfully read"+ + " %d byte(s), sha384 %v", len(data), actualHash) + return nil +} + +// UnmarshalBinary converts []bytes into a Filter +// conforms to encoding.BinaryUnmarshaler +func (f *Filter) UnmarshalBinary(data []byte) (err error) { + f.lock.Lock() + defer f.lock.Unlock() + + buf := bytes.NewBuffer(data) + + var k uint64 + k, f.n, f.m, err = unmarshalBinaryHeader(buf) + if err != nil { + return err + } + + f.keys, err = unmarshalBinaryKeys(buf, k) + if err != nil { + return err + } + + f.bits, err = unmarshalBinaryBits(buf, f.m) + if err != nil { + return err + } + + return checkBinaryHash(buf, data) +} diff --git a/vendor/github.com/steakknife/bloomfilter/bloomfilter.go b/vendor/github.com/steakknife/bloomfilter/bloomfilter.go new file mode 100644 index 000000000..822506365 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/bloomfilter.go @@ -0,0 +1,123 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "hash" + "sync" +) + +// Filter is an opaque Bloom filter type +type Filter struct { + lock sync.RWMutex + bits []uint64 + keys []uint64 + m uint64 // number of bits the "bits" field should recognize + n uint64 // number of inserted elements +} + +// Hashable -> hashes +func (f *Filter) hash(v hash.Hash64) []uint64 { + rawHash := v.Sum64() + n := len(f.keys) + hashes := make([]uint64, n) + for i := 0; i < n; i++ { + hashes[i] = rawHash ^ f.keys[i] + } + return hashes +} + +// M is the size of Bloom filter, in bits +func (f *Filter) M() uint64 { + return f.m +} + +// K is the count of keys +func (f *Filter) K() uint64 { + return uint64(len(f.keys)) +} + +// Add a hashable item, v, to the filter +func (f *Filter) Add(v hash.Hash64) { + f.lock.Lock() + defer f.lock.Unlock() + + for _, i := range f.hash(v) { + // f.setBit(i) + i %= f.m + f.bits[i>>6] |= 1 << uint(i&0x3f) + } + f.n++ +} + +// Contains tests if f contains v +// false: f definitely does not contain value v +// true: f maybe contains value v +func (f *Filter) Contains(v hash.Hash64) bool { + f.lock.RLock() + defer f.lock.RUnlock() + + r := uint64(1) + for _, i := range f.hash(v) { + // r |= f.getBit(k) + i %= f.m + r &= (f.bits[i>>6] >> uint(i&0x3f)) & 1 + } + return uint64ToBool(r) +} + +// Copy f to a new Bloom filter +func (f *Filter) Copy() (*Filter, error) { + f.lock.RLock() + defer f.lock.RUnlock() + + out, err := f.NewCompatible() + if err != nil { + return nil, err + } + copy(out.bits, f.bits) + out.n = f.n + return out, nil +} + +// UnionInPlace merges Bloom filter f2 into f +func (f *Filter) UnionInPlace(f2 *Filter) error { + if !f.IsCompatible(f2) { + return errIncompatibleBloomFilters() + } + + f.lock.Lock() + defer f.lock.Unlock() + + for i, bitword := range f2.bits { + f.bits[i] |= bitword + } + return nil +} + +// Union merges f2 and f2 into a new Filter out +func (f *Filter) Union(f2 *Filter) (out *Filter, err error) { + if !f.IsCompatible(f2) { + return nil, errIncompatibleBloomFilters() + } + + f.lock.RLock() + defer f.lock.RUnlock() + + out, err = f.NewCompatible() + if err != nil { + return nil, err + } + for i, bitword := range f2.bits { + out.bits[i] = f.bits[i] | bitword + } + return out, nil +} diff --git a/vendor/github.com/steakknife/bloomfilter/conformance.go b/vendor/github.com/steakknife/bloomfilter/conformance.go new file mode 100644 index 000000000..2963686f8 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/conformance.go @@ -0,0 +1,29 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "encoding" + "encoding/gob" + "io" +) + +// compile-time conformance tests +var ( + _ encoding.BinaryMarshaler = (*Filter)(nil) + _ encoding.BinaryUnmarshaler = (*Filter)(nil) + _ encoding.TextMarshaler = (*Filter)(nil) + _ encoding.TextUnmarshaler = (*Filter)(nil) + _ io.ReaderFrom = (*Filter)(nil) + _ io.WriterTo = (*Filter)(nil) + _ gob.GobDecoder = (*Filter)(nil) + _ gob.GobEncoder = (*Filter)(nil) +) diff --git a/vendor/github.com/steakknife/bloomfilter/debug.go b/vendor/github.com/steakknife/bloomfilter/debug.go new file mode 100644 index 000000000..e88b934c1 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/debug.go @@ -0,0 +1,37 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "log" + "os" +) + +const debugVar = "GOLANG_STEAKKNIFE_BLOOMFILTER_DEBUG" + +// EnableDebugging permits debug() logging of details to stderr +func EnableDebugging() { + err := os.Setenv(debugVar, "1") + if err != nil { + panic("Unable to Setenv " + debugVar) + } +} + +func debugging() bool { + return os.Getenv(debugVar) != "" +} + +// debug printing when debugging() is true +func debug(format string, a ...interface{}) { + if debugging() { + log.Printf(format, a...) + } +} diff --git a/vendor/github.com/steakknife/bloomfilter/errors.go b/vendor/github.com/steakknife/bloomfilter/errors.go new file mode 100644 index 000000000..b279739b3 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/errors.go @@ -0,0 +1,34 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import "fmt" + +func errHash() error { + return fmt.Errorf( + "Hash mismatch, the Bloom filter is probably corrupt") +} +func errK() error { + return fmt.Errorf( + "keys must have length %d or greater", KMin) +} +func errM() error { + return fmt.Errorf( + "m (number of bits in the Bloom filter) must be >= %d", MMin) +} +func errUniqueKeys() error { + return fmt.Errorf( + "Bloom filter keys must be unique") +} +func errIncompatibleBloomFilters() error { + return fmt.Errorf( + "Cannot perform union on two incompatible Bloom filters") +} diff --git a/vendor/github.com/steakknife/bloomfilter/fileio.go b/vendor/github.com/steakknife/bloomfilter/fileio.go new file mode 100644 index 000000000..a47969956 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/fileio.go @@ -0,0 +1,105 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "compress/gzip" + "io" + "io/ioutil" + "os" +) + +// ReadFrom r and overwrite f with new Bloom filter data +func (f *Filter) ReadFrom(r io.Reader) (n int64, err error) { + f2, n, err := ReadFrom(r) + if err != nil { + return -1, err + } + f.lock.Lock() + defer f.lock.Unlock() + f.m = f2.m + f.n = f2.n + f.bits = f2.bits + f.keys = f2.keys + return n, nil +} + +// ReadFrom Reader r into a lossless-compressed Bloom filter f +func ReadFrom(r io.Reader) (f *Filter, n int64, err error) { + rawR, err := gzip.NewReader(r) + if err != nil { + return nil, -1, err + } + defer func() { + err = rawR.Close() + }() + + content, err := ioutil.ReadAll(rawR) + if err != nil { + return nil, -1, err + } + + f = new(Filter) + n = int64(len(content)) + err = f.UnmarshalBinary(content) + if err != nil { + return nil, -1, err + } + return f, n, nil +} + +// ReadFile from filename into a lossless-compressed Bloom Filter f +// Suggested file extension: .bf.gz +func ReadFile(filename string) (f *Filter, n int64, err error) { + r, err := os.Open(filename) + if err != nil { + return nil, -1, err + } + defer func() { + err = r.Close() + }() + + return ReadFrom(r) +} + +// WriteTo a Writer w from lossless-compressed Bloom Filter f +func (f *Filter) WriteTo(w io.Writer) (n int64, err error) { + f.lock.RLock() + defer f.lock.RUnlock() + + rawW := gzip.NewWriter(w) + defer func() { + err = rawW.Close() + }() + + content, err := f.MarshalBinary() + if err != nil { + return -1, err + } + + intN, err := rawW.Write(content) + n = int64(intN) + return n, err +} + +// WriteFile filename from a a lossless-compressed Bloom Filter f +// Suggested file extension: .bf.gz +func (f *Filter) WriteFile(filename string) (n int64, err error) { + w, err := os.Create(filename) + if err != nil { + return -1, err + } + defer func() { + err = w.Close() + }() + + return f.WriteTo(w) +} diff --git a/vendor/github.com/steakknife/bloomfilter/gob.go b/vendor/github.com/steakknife/bloomfilter/gob.go new file mode 100644 index 000000000..0d99e55d4 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/gob.go @@ -0,0 +1,23 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import _ "encoding/gob" // make sure gob is available + +// GobDecode conforms to interface gob.GobDecoder +func (f *Filter) GobDecode(data []byte) error { + return f.UnmarshalBinary(data) +} + +// GobEncode conforms to interface gob.GobEncoder +func (f *Filter) GobEncode() ([]byte, error) { + return f.MarshalBinary() +} diff --git a/vendor/github.com/steakknife/bloomfilter/iscompatible.go b/vendor/github.com/steakknife/bloomfilter/iscompatible.go new file mode 100644 index 000000000..2073d8083 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/iscompatible.go @@ -0,0 +1,41 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import "unsafe" + +func uint64ToBool(x uint64) bool { + return *(*bool)(unsafe.Pointer(&x)) // #nosec +} + +// returns 0 if equal, does not compare len(b0) with len(b1) +func noBranchCompareUint64s(b0, b1 []uint64) uint64 { + r := uint64(0) + for i, b0i := range b0 { + r |= b0i ^ b1[i] + } + return r +} + +// IsCompatible is true if f and f2 can be Union()ed together +func (f *Filter) IsCompatible(f2 *Filter) bool { + f.lock.RLock() + defer f.lock.RUnlock() + + f.lock.RLock() + defer f2.lock.RUnlock() + + // 0 is true, non-0 is false + compat := f.M() ^ f2.M() + compat |= f.K() ^ f2.K() + compat |= noBranchCompareUint64s(f.keys, f2.keys) + return uint64ToBool(^compat) +} diff --git a/vendor/github.com/steakknife/bloomfilter/new.go b/vendor/github.com/steakknife/bloomfilter/new.go new file mode 100644 index 000000000..bf4323a7e --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/new.go @@ -0,0 +1,134 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "crypto/rand" + "encoding/binary" + "log" +) + +const ( + // MMin is the minimum Bloom filter bits count + MMin = 2 + // KMin is the minimum number of keys + KMin = 1 + // Uint64Bytes is the number of bytes in type uint64 + Uint64Bytes = 8 +) + +// New Filter with CSPRNG keys +// +// m is the size of the Bloom filter, in bits, >= 2 +// +// k is the number of random keys, >= 1 +func New(m, k uint64) (*Filter, error) { + return NewWithKeys(m, newRandKeys(k)) +} + +func newRandKeys(k uint64) []uint64 { + keys := make([]uint64, k) + err := binary.Read(rand.Reader, binary.LittleEndian, keys) + if err != nil { + log.Panicf( + "Cannot read %d bytes from CSRPNG crypto/rand.Read (err=%v)", + Uint64Bytes, err, + ) + } + return keys +} + +// NewCompatible Filter compatible with f +func (f *Filter) NewCompatible() (*Filter, error) { + return NewWithKeys(f.m, f.keys) +} + +// NewOptimal Bloom filter with random CSPRNG keys +func NewOptimal(maxN uint64, p float64) (*Filter, error) { + m := OptimalM(maxN, p) + k := OptimalK(m, maxN) + debug("New optimal bloom filter ::"+ + " requested max elements (n):%d,"+ + " probability of collision (p):%1.10f "+ + "-> recommends -> bits (m): %d (%f GiB), "+ + "number of keys (k): %d", + maxN, p, m, float64(m)/(gigabitsPerGiB), k) + return New(m, k) +} + +// UniqueKeys is true if all keys are unique +func UniqueKeys(keys []uint64) bool { + for j := 0; j < len(keys)-1; j++ { + elem := keys[j] + for i := 1; i < j; i++ { + if keys[i] == elem { + return false + } + } + } + return true +} + +// NewWithKeys creates a new Filter from user-supplied origKeys +func NewWithKeys(m uint64, origKeys []uint64) (f *Filter, err error) { + bits, err := newBits(m) + if err != nil { + return nil, err + } + keys, err := newKeysCopy(origKeys) + if err != nil { + return nil, err + } + return &Filter{ + m: m, + n: 0, + bits: bits, + keys: keys, + }, nil +} + +func newBits(m uint64) ([]uint64, error) { + if m < MMin { + return nil, errM() + } + return make([]uint64, (m+63)/64), nil +} + +func newKeysBlank(k uint64) ([]uint64, error) { + if k < KMin { + return nil, errK() + } + return make([]uint64, k), nil +} + +func newKeysCopy(origKeys []uint64) (keys []uint64, err error) { + if !UniqueKeys(origKeys) { + return nil, errUniqueKeys() + } + keys, err = newKeysBlank(uint64(len(origKeys))) + if err != nil { + return keys, err + } + copy(keys, origKeys) + return keys, err +} + +func newWithKeysAndBits(m uint64, keys []uint64, bits []uint64, n uint64) ( + f *Filter, err error, +) { + f, err = NewWithKeys(m, keys) + if err != nil { + return nil, err + } + copy(f.bits, bits) + f.n = n + return f, nil +} diff --git a/vendor/github.com/steakknife/bloomfilter/optimal.go b/vendor/github.com/steakknife/bloomfilter/optimal.go new file mode 100644 index 000000000..a8361434a --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/optimal.go @@ -0,0 +1,28 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import "math" + +const gigabitsPerGiB float64 = 8.0 * 1024 * 1024 * 1024 + +// OptimalK calculates the optimal k value for creating a new Bloom filter +// maxn is the maximum anticipated number of elements +func OptimalK(m, maxN uint64) uint64 { + return uint64(math.Ceil(float64(m) * math.Ln2 / float64(maxN))) +} + +// OptimalM calculates the optimal m value for creating a new Bloom filter +// p is the desired false positive probability +// optimal m = ceiling( - n * ln(p) / ln(2)**2 ) +func OptimalM(maxN uint64, p float64) uint64 { + return uint64(math.Ceil(-float64(maxN) * math.Log(p) / (math.Ln2 * math.Ln2))) +} diff --git a/vendor/github.com/steakknife/bloomfilter/statistics.go b/vendor/github.com/steakknife/bloomfilter/statistics.go new file mode 100644 index 000000000..fe50ffa54 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/statistics.go @@ -0,0 +1,43 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "math" + + "github.com/steakknife/hamming" +) + +// PreciseFilledRatio is an exhaustive count # of 1's +func (f *Filter) PreciseFilledRatio() float64 { + f.lock.RLock() + defer f.lock.RUnlock() + + return float64(hamming.CountBitsUint64s(f.bits)) / float64(f.M()) +} + +// N is how many elements have been inserted +// (actually, how many Add()s have been performed?) +func (f *Filter) N() uint64 { + f.lock.RLock() + defer f.lock.RUnlock() + + return f.n +} + +// FalsePosititveProbability is the upper-bound probability of false positives +// (1 - exp(-k*(n+0.5)/(m-1))) ** k +func (f *Filter) FalsePosititveProbability() float64 { + k := float64(f.K()) + n := float64(f.N()) + m := float64(f.M()) + return math.Pow(1.0-math.Exp(-k)*(n+0.5)/(m-1), k) +} diff --git a/vendor/github.com/steakknife/bloomfilter/textmarshaler.go b/vendor/github.com/steakknife/bloomfilter/textmarshaler.go new file mode 100644 index 000000000..7ed08eb7f --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/textmarshaler.go @@ -0,0 +1,49 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import "fmt" + +// MarshalText conforms to encoding.TextMarshaler +func (f *Filter) MarshalText() (text []byte, err error) { + f.lock.RLock() + defer f.lock.RUnlock() + + s := fmt.Sprintln("k") + s += fmt.Sprintln(f.K()) + s += fmt.Sprintln("n") + s += fmt.Sprintln(f.n) + s += fmt.Sprintln("m") + s += fmt.Sprintln(f.m) + + s += fmt.Sprintln("keys") + for key := range f.keys { + s += fmt.Sprintf(keyFormat, key) + nl() + } + + s += fmt.Sprintln("bits") + for w := range f.bits { + s += fmt.Sprintf(bitsFormat, w) + nl() + } + + _, hash, err := f.marshal() + if err != nil { + return nil, err + } + s += fmt.Sprintln("sha384") + for b := range hash { + s += fmt.Sprintf("%02x", b) + } + s += nl() + + text = []byte(s) + return text, nil +} diff --git a/vendor/github.com/steakknife/bloomfilter/textunmarshaler.go b/vendor/github.com/steakknife/bloomfilter/textunmarshaler.go new file mode 100644 index 000000000..93240a1a7 --- /dev/null +++ b/vendor/github.com/steakknife/bloomfilter/textunmarshaler.go @@ -0,0 +1,150 @@ +// Package bloomfilter is face-meltingly fast, thread-safe, +// marshalable, unionable, probability- and +// optimal-size-calculating Bloom filter in go +// +// https://github.com/steakknife/bloomfilter +// +// Copyright © 2014, 2015, 2018 Barry Allard +// +// MIT license +// +package bloomfilter + +import ( + "bytes" + "crypto/hmac" + "crypto/sha512" + "fmt" + "io" +) + +const ( + keyFormat = "%016x" + bitsFormat = "%016x" +) + +func nl() string { + return fmt.Sprintln() +} + +func unmarshalTextHeader(r io.Reader) (k, n, m uint64, err error) { + format := "k" + nl() + "%d" + nl() + format += "n" + nl() + "%d" + nl() + format += "m" + nl() + "%d" + nl() + format += "keys" + nl() + + _, err = fmt.Fscanf(r, format, k, n, m) + return k, n, m, err +} + +func unmarshalTextKeys(r io.Reader, keys []uint64) (err error) { + for i := range keys { + _, err = fmt.Fscanf(r, keyFormat, keys[i]) + if err != nil { + return err + } + } + return nil +} + +func unmarshalTextBits(r io.Reader, bits []uint64) (err error) { + _, err = fmt.Fscanf(r, "bits") + if err != nil { + return err + } + + for i := range bits { + _, err = fmt.Fscanf(r, bitsFormat, bits[i]) + if err != nil { + return err + } + } + + return nil +} + +func unmarshalAndCheckTextHash(r io.Reader, f *Filter) (err error) { + _, err = fmt.Fscanf(r, "sha384") + if err != nil { + return err + } + + actualHash := [sha512.Size384]byte{} + + for i := range actualHash { + _, err = fmt.Fscanf(r, "%02x", actualHash[i]) + if err != nil { + return err + } + } + + _, expectedHash, err := f.marshal() + if err != nil { + return err + } + + if !hmac.Equal(expectedHash[:], actualHash[:]) { + return errHash() + } + + return nil +} + +// UnmarshalText conforms to TextUnmarshaler +func UnmarshalText(text []byte) (f *Filter, err error) { + r := bytes.NewBuffer(text) + k, n, m, err := unmarshalTextHeader(r) + if err != nil { + return nil, err + } + + keys, err := newKeysBlank(k) + if err != nil { + return nil, err + } + + err = unmarshalTextKeys(r, keys) + if err != nil { + return nil, err + } + + bits, err := newBits(m) + if err != nil { + return nil, err + } + + err = unmarshalTextBits(r, bits) + if err != nil { + return nil, err + } + + f, err = newWithKeysAndBits(m, keys, bits, n) + if err != nil { + return nil, err + } + + err = unmarshalAndCheckTextHash(r, f) + if err != nil { + return nil, err + } + + return f, nil +} + +// UnmarshalText method overwrites f with data decoded from text +func (f *Filter) UnmarshalText(text []byte) error { + f.lock.Lock() + defer f.lock.Unlock() + + f2, err := UnmarshalText(text) + if err != nil { + return err + } + + f.m = f2.m + f.n = f2.n + copy(f.bits, f2.bits) + copy(f.keys, f2.keys) + + return nil +} diff --git a/vendor/github.com/steakknife/hamming/.gitignore b/vendor/github.com/steakknife/hamming/.gitignore new file mode 100644 index 000000000..928a2c6d1 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/.gitignore @@ -0,0 +1,2 @@ +*.o +/coverage.out diff --git a/vendor/github.com/steakknife/hamming/.travis.yml b/vendor/github.com/steakknife/hamming/.travis.yml new file mode 100644 index 000000000..738121280 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/.travis.yml @@ -0,0 +1,14 @@ +language: go +dist: trusty +sudo: false +go: + - "1.8.x" + - "1.9.x" + - "1.10.x" + - master +before_script: + - "go get -u gopkg.in/alecthomas/gometalinter.v2" + - "gometalinter.v2 --install" +script: + - "go test -v -cover -benchmem -bench=. $(go list ./... | grep -v /vendor/ | sed \"s&_${PWD}&.&\")" + - "gometalinter.v2 --enable-all --exclude=dupl ./..." diff --git a/vendor/github.com/steakknife/hamming/MIT-LICENSE.txt b/vendor/github.com/steakknife/hamming/MIT-LICENSE.txt new file mode 100644 index 000000000..924f4c091 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/MIT-LICENSE.txt @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright © 2014, 2015, 2016 Barry Allard + +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/steakknife/hamming/README.md b/vendor/github.com/steakknife/hamming/README.md new file mode 100644 index 000000000..23f69bdf5 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/README.md @@ -0,0 +1,82 @@ +[![GoDoc](https://godoc.org/github.com/steakknife/hamming?status.png)](https://godoc.org/github.com/steakknife/hamming) [![Build Status](https://travis-ci.org/steakknife/hamming.svg?branch=master)](https://travis-ci.org/steakknife/hamming) + + +# hamming distance calculations in Go + +Copyright © 2014, 2015, 2016, 2018 Barry Allard + +[MIT license](MIT-LICENSE.txt) + +## Performance + +``` +$ go test -bench=. +BenchmarkCountBitsInt8PopCnt-4 300000000 4.30 ns/op +BenchmarkCountBitsInt16PopCnt-4 300000000 3.83 ns/op +BenchmarkCountBitsInt32PopCnt-4 300000000 3.64 ns/op +BenchmarkCountBitsInt64PopCnt-4 500000000 3.60 ns/op +BenchmarkCountBitsIntPopCnt-4 300000000 5.72 ns/op +BenchmarkCountBitsUint8PopCnt-4 1000000000 2.98 ns/op +BenchmarkCountBitsUint16PopCnt-4 500000000 3.23 ns/op +BenchmarkCountBitsUint32PopCnt-4 500000000 3.00 ns/op +BenchmarkCountBitsUint64PopCnt-4 1000000000 2.94 ns/op +BenchmarkCountBitsUintPopCnt-4 300000000 5.04 ns/op +BenchmarkCountBitsBytePopCnt-4 300000000 3.99 ns/op +BenchmarkCountBitsRunePopCnt-4 300000000 3.83 ns/op +BenchmarkCountBitsInt8-4 2000000000 0.74 ns/op +BenchmarkCountBitsInt16-4 2000000000 1.54 ns/op +BenchmarkCountBitsInt32-4 1000000000 2.63 ns/op +BenchmarkCountBitsInt64-4 1000000000 2.56 ns/op +BenchmarkCountBitsInt-4 200000000 7.23 ns/op +BenchmarkCountBitsUint16-4 2000000000 1.51 ns/op +BenchmarkCountBitsUint32-4 500000000 4.00 ns/op +BenchmarkCountBitsUint64-4 1000000000 2.64 ns/op +BenchmarkCountBitsUint64Alt-4 200000000 7.60 ns/op +BenchmarkCountBitsUint-4 300000000 5.48 ns/op +BenchmarkCountBitsUintReference-4 100000000 19.2 ns/op +BenchmarkCountBitsByte-4 2000000000 0.75 ns/op +BenchmarkCountBitsByteAlt-4 1000000000 2.37 ns/op +BenchmarkCountBitsRune-4 500000000 2.85 ns/op +PASS +ok _/Users/bmf/Projects/hamming 58.305s +$ +``` + +## Usage + +```go +import 'github.com/steakknife/hamming' + +// ... + +// hamming distance between values +hamming.Byte(0xFF, 0x00) // 8 +hamming.Byte(0x00, 0x00) // 0 + +// just count bits in a byte +hamming.CountBitsByte(0xA5), // 4 +``` + +See help in the [docs](https://godoc.org/github.com/steakknife/hamming) + +## Get + + go get -u github.com/steakknife/hamming # master is always stable + +## Source + +- On the web: https://github.com/steakknife/hamming + +- Git: `git clone https://github.com/steakknife/hamming` + +## Contact + +- [Feedback](mailto:barry.allard@gmail.com) + +- [Issues](https://github.com/steakknife/hamming/issues) + +## License + +[MIT license](MIT-LICENSE.txt) + +Copyright © 2014, 2015, 2016 Barry Allard diff --git a/vendor/github.com/steakknife/hamming/doc.go b/vendor/github.com/steakknife/hamming/doc.go new file mode 100644 index 000000000..179e29da9 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/doc.go @@ -0,0 +1,35 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +// +// Usage +// +// For functions named CountBits.+s?. The plural forms are for slices. +// The CountBits.+ forms are Population Count only, where the bare-type +// forms are Hamming distance (number of bits different) between two values. +// +// Optimized assembly .+PopCnt forms are available on amd64, and operate just +// like the regular forms (Must check and guard on HasPopCnt() first before +// trying to call .+PopCnt functions). +// +// import 'github.com/steakknife/hamming' +// +// // ... +// +// // hamming distance between values +// hamming.Byte(0xFF, 0x00) // 8 +// hamming.Byte(0x00, 0x00) // 0 +// +// // just count bits in a byte +// hamming.CountBitsByte(0xA5), // 4 +// +// Got rune? use int32 +// Got uint8? use byte +// +package hamming diff --git a/vendor/github.com/steakknife/hamming/hamming.go b/vendor/github.com/steakknife/hamming/hamming.go new file mode 100644 index 000000000..269e91a4d --- /dev/null +++ b/vendor/github.com/steakknife/hamming/hamming.go @@ -0,0 +1,70 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +// Int8 hamming distance of two int8's +func Int8(x, y int8) int { + return CountBitsInt8(x ^ y) +} + +// Int16 hamming distance of two int16's +func Int16(x, y int16) int { + return CountBitsInt16(x ^ y) +} + +// Int32 hamming distance of two int32's +func Int32(x, y int32) int { + return CountBitsInt32(x ^ y) +} + +// Int64 hamming distance of two int64's +func Int64(x, y int64) int { + return CountBitsInt64(x ^ y) +} + +// Int hamming distance of two ints +func Int(x, y int) int { + return CountBitsInt(x ^ y) +} + +// Uint8 hamming distance of two uint8's +func Uint8(x, y uint8) int { + return CountBitsUint8(x ^ y) +} + +// Uint16 hamming distance of two uint16's +func Uint16(x, y uint16) int { + return CountBitsUint16(x ^ y) +} + +// Uint32 hamming distance of two uint32's +func Uint32(x, y uint32) int { + return CountBitsUint32(x ^ y) +} + +// Uint64 hamming distance of two uint64's +func Uint64(x, y uint64) int { + return CountBitsUint64(x ^ y) +} + +// Uint hamming distance of two uint's +func Uint(x, y uint) int { + return CountBitsUint(x ^ y) +} + +// Byte hamming distance of two bytes +func Byte(x, y byte) int { + return CountBitsByte(x ^ y) +} + +// Rune hamming distance of two runes +func Rune(x, y rune) int { + return CountBitsRune(x ^ y) +} diff --git a/vendor/github.com/steakknife/hamming/popcnt_amd64.go b/vendor/github.com/steakknife/hamming/popcnt_amd64.go new file mode 100644 index 000000000..a1a6d92bd --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcnt_amd64.go @@ -0,0 +1,65 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +import "strconv" + +// HasPopCnt returns true if *PopCnt functions are callable +func HasPopCnt() (ret bool) + +// CountBitsInt8PopCnt count 1's in x +func CountBitsInt8PopCnt(x int8) (ret int) + +// CountBitsInt16PopCnt count 1's in x +func CountBitsInt16PopCnt(x int16) (ret int) + +// CountBitsInt32PopCnt count 1's in x +func CountBitsInt32PopCnt(x int32) (ret int) + +// CountBitsInt64PopCnt count 1's in x +func CountBitsInt64PopCnt(x int64) (ret int) + +// CountBitsIntPopCnt count 1's in x +func CountBitsIntPopCnt(x int) int { + if strconv.IntSize == 64 { + return CountBitsInt64PopCnt(int64(x)) + } else if strconv.IntSize == 32 { + return CountBitsInt32PopCnt(int32(x)) + } + panic("strconv.IntSize must be 32 or 64") +} + +// CountBitsUint8PopCnt count 1's in x +func CountBitsUint8PopCnt(x uint8) (ret int) + +// CountBitsUint16PopCnt count 1's in x +func CountBitsUint16PopCnt(x uint16) (ret int) + +// CountBitsUint32PopCnt count 1's in x +func CountBitsUint32PopCnt(x uint32) (ret int) + +// CountBitsUint64PopCnt count 1's in x +func CountBitsUint64PopCnt(x uint64) (ret int) + +// CountBitsUintPopCnt count 1's in x +func CountBitsUintPopCnt(x uint) int { + if strconv.IntSize == 64 { + return CountBitsUint64PopCnt(uint64(x)) + } else if strconv.IntSize == 32 { + return CountBitsUint32PopCnt(uint32(x)) + } + panic("strconv.IntSize must be 32 or 64") +} + +// CountBitsBytePopCnt count 1's in x +func CountBitsBytePopCnt(x byte) (ret int) + +// CountBitsRunePopCnt count 1's in x +func CountBitsRunePopCnt(x rune) (ret int) diff --git a/vendor/github.com/steakknife/hamming/popcnt_amd64.s b/vendor/github.com/steakknife/hamming/popcnt_amd64.s new file mode 100644 index 000000000..51c51248a --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcnt_amd64.s @@ -0,0 +1,64 @@ +// +// hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016 Barry Allard +// +// MIT license +// + +#include "textflag.h" + +TEXT ·CountBitsInt8PopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsBytePopCnt(SB) + +TEXT ·CountBitsInt16PopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint16PopCnt(SB) + +TEXT ·CountBitsInt32PopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint32PopCnt(SB) + +TEXT ·CountBitsInt64PopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint64PopCnt(SB) + +TEXT ·CountBitsBytePopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint8PopCnt(SB) + +TEXT ·CountBitsRunePopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint32PopCnt(SB) + +TEXT ·CountBitsUint8PopCnt(SB),NOSPLIT,$0 + XORQ AX, AX + MOVB x+0(FP), AX + POPCNTQ AX, AX + MOVQ AX, ret+8(FP) + RET + +TEXT ·CountBitsUint16PopCnt(SB),NOSPLIT,$0 + XORQ AX, AX + MOVW x+0(FP), AX + POPCNTQ AX, AX + MOVQ AX, ret+8(FP) + RET + +TEXT ·CountBitsUint32PopCnt(SB),NOSPLIT,$0 + XORQ AX, AX + MOVL x+0(FP), AX + POPCNTQ AX, AX + MOVQ AX, ret+8(FP) + RET + +TEXT ·CountBitsUint64PopCnt(SB),NOSPLIT,$0 + POPCNTQ x+0(FP), AX + MOVQ AX, ret+8(FP) + RET + +// func hasPopCnt() (ret bool) +TEXT ·HasPopCnt(SB),NOSPLIT,$0 + MOVL $1, AX + CPUID + SHRL $23, CX // bit 23: Advanced Bit Manipulation Bit (ABM) -> POPCNTQ + ANDL $1, CX + MOVB CX, ret+0(FP) + RET diff --git a/vendor/github.com/steakknife/hamming/popcount.go b/vendor/github.com/steakknife/hamming/popcount.go new file mode 100644 index 000000000..848103bbf --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcount.go @@ -0,0 +1,134 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +import "strconv" + +// References: check out Hacker's Delight, about p. 70 + +func table() [256]uint8 { + return [256]uint8{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + } +} + +// CountBitsByteAlt table-less, branch-free implementation +func CountBitsByteAlt(x byte) int { + x = (x & 0x55) + ((x >> 1) & 0x55) + x = (x & 0x33) + ((x >> 2) & 0x33) + return int((x & 0x0f) + ((x >> 4) & 0x0f)) +} + +// CountBitsInt8 count 1's in x +func CountBitsInt8(x int8) int { return CountBitsByte(byte(x)) } + +// CountBitsInt16 count 1's in x +func CountBitsInt16(x int16) int { return CountBitsUint16(uint16(x)) } + +// CountBitsInt32 count 1's in x +func CountBitsInt32(x int32) int { return CountBitsUint32(uint32(x)) } + +// CountBitsInt64 count 1's in x +func CountBitsInt64(x int64) int { return CountBitsUint64(uint64(x)) } + +// CountBitsInt count 1's in x +func CountBitsInt(x int) int { return CountBitsUint(uint(x)) } + +// CountBitsByte count 1's in x +func CountBitsByte(x byte) int { return CountBitsUint8(x) } + +// CountBitsRune count 1's in x +func CountBitsRune(x rune) int { return CountBitsInt32(x) } + +// CountBitsUint8 count 1's in x +func CountBitsUint8(x uint8) int { return int(table()[x]) } + +// CountBitsUint16 count 1's in x +func CountBitsUint16(x uint16) int { + return int(table()[x&0xFF] + table()[(x>>8)&0xFF]) +} + +const ( + m1d uint32 = 0x55555555 + m2d = 0x33333333 + m4d = 0x0f0f0f0f +) + +// CountBitsUint32 count 1's in x +func CountBitsUint32(x uint32) int { + x -= ((x >> 1) & m1d) + x = (x & m2d) + ((x >> 2) & m2d) + x = (x + (x >> 4)) & m4d + x += x >> 8 + x += x >> 16 + return int(x & 0x3f) +} + +const ( + m1q uint64 = 0x5555555555555555 + m2q = 0x3333333333333333 + m4q = 0x0f0f0f0f0f0f0f0f + hq = 0x0101010101010101 +) + +// CountBitsUint64 count 1's in x +func CountBitsUint64(x uint64) int { + // put count of each 2 bits into those 2 bits + x -= (x >> 1) & m1q + + // put count of each 4 bits into those 4 bits + x = (x & m2q) + ((x >> 2) & m2q) + + // put count of each 8 bits into those 8 bits + x = (x + (x >> 4)) & m4q + + // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... + return int((x * hq) >> 56) +} + +// CountBitsUint64Alt count 1's in x +func CountBitsUint64Alt(x uint64) int { + return CountBitsUint32(uint32(x>>32)) + CountBitsUint32(uint32(x)) +} + +// CountBitsUintReference count 1's in x +func CountBitsUintReference(x uint) int { + c := 0 + for x != 0 { + x &= x - 1 + c++ + } + return c +} + +// CountBitsUint count 1's in x +func CountBitsUint(x uint) int { + if strconv.IntSize == 64 { + return CountBitsUint64(uint64(x)) + } else if strconv.IntSize == 32 { + return CountBitsUint32(uint32(x)) + } + panic("strconv.IntSize must be 32 or 64 bits") +} diff --git a/vendor/github.com/steakknife/hamming/popcount_slices.go b/vendor/github.com/steakknife/hamming/popcount_slices.go new file mode 100644 index 000000000..957fe1165 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcount_slices.go @@ -0,0 +1,123 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +// CountBitsInt8s count 1's in b +func CountBitsInt8s(b []int8) int { + c := 0 + for _, x := range b { + c += CountBitsInt8(x) + } + return c +} + +// CountBitsInt16s count 1's in b +func CountBitsInt16s(b []int16) int { + c := 0 + for _, x := range b { + c += CountBitsInt16(x) + } + return c +} + +// CountBitsInt32s count 1's in b +func CountBitsInt32s(b []int32) int { + c := 0 + for _, x := range b { + c += CountBitsInt32(x) + } + return c +} + +// CountBitsInt64s count 1's in b +func CountBitsInt64s(b []int64) int { + c := 0 + for _, x := range b { + c += CountBitsInt64(x) + } + return c +} + +// CountBitsInts count 1's in b +func CountBitsInts(b []int) int { + c := 0 + for _, x := range b { + c += CountBitsInt(x) + } + return c +} + +// CountBitsUint8s count 1's in b +func CountBitsUint8s(b []uint8) int { + c := 0 + for _, x := range b { + c += CountBitsUint8(x) + } + return c +} + +// CountBitsUint16s count 1's in b +func CountBitsUint16s(b []uint16) int { + c := 0 + for _, x := range b { + c += CountBitsUint16(x) + } + return c +} + +// CountBitsUint32s count 1's in b +func CountBitsUint32s(b []uint32) int { + c := 0 + for _, x := range b { + c += CountBitsUint32(x) + } + return c +} + +// CountBitsUint64s count 1's in b +func CountBitsUint64s(b []uint64) int { + c := 0 + for _, x := range b { + c += CountBitsUint64(x) + } + return c +} + +// CountBitsUints count 1's in b +func CountBitsUints(b []uint) int { + c := 0 + for _, x := range b { + c += CountBitsUint(x) + } + return c +} + +// CountBitsBytes count 1's in b +func CountBitsBytes(b []byte) int { + c := 0 + for _, x := range b { + c += CountBitsByte(x) + } + return c +} + +// CountBitsRunes count 1's in b +func CountBitsRunes(b []rune) int { + c := 0 + for _, x := range b { + c += CountBitsRune(x) + } + return c +} + +// CountBitsString count 1's in s +func CountBitsString(s string) int { + return CountBitsBytes([]byte(s)) +} diff --git a/vendor/github.com/steakknife/hamming/popcount_slices_amd64.go b/vendor/github.com/steakknife/hamming/popcount_slices_amd64.go new file mode 100644 index 000000000..b3e13fdf9 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcount_slices_amd64.go @@ -0,0 +1,72 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +import ( + "strconv" + "unsafe" +) + +// CountBitsInt8sPopCnt count 1's in x +func CountBitsInt8sPopCnt(x []int8) (ret int) + +// CountBitsInt16sPopCnt count 1's in x +func CountBitsInt16sPopCnt(x []int16) (ret int) + +// CountBitsInt32sPopCnt count 1's in x +func CountBitsInt32sPopCnt(x []int32) (ret int) + +// CountBitsInt64sPopCnt count 1's in x +func CountBitsInt64sPopCnt(x []int64) (ret int) + +// CountBitsIntsPopCnt count 1's in x +func CountBitsIntsPopCnt(x []int) int { + if strconv.IntSize == 64 { + y := (*[]int64)(unsafe.Pointer(&x)) // #nosec G103 + return CountBitsInt64sPopCnt(*y) + } else if strconv.IntSize == 32 { + y := (*[]int32)(unsafe.Pointer(&x)) // #nosec G103 + return CountBitsInt32sPopCnt(*y) + } + panic("strconv.IntSize must be 32 or 64 bits") +} + +// CountBitsUint8sPopCnt count 1's in x +func CountBitsUint8sPopCnt(x []uint8) (ret int) + +// CountBitsUint16sPopCnt count 1's in x +func CountBitsUint16sPopCnt(x []uint16) (ret int) + +// CountBitsUint32sPopCnt count 1's in x +func CountBitsUint32sPopCnt(x []uint32) (ret int) + +// CountBitsUint64sPopCnt count 1's in x +func CountBitsUint64sPopCnt(x []uint64) (ret int) + +// CountBitsUintsPopCnt count 1's in x +func CountBitsUintsPopCnt(x []uint) int { + if strconv.IntSize == 64 { + y := (*[]uint64)(unsafe.Pointer(&x)) // #nosec G103 + return CountBitsUint64sPopCnt(*y) + } else if strconv.IntSize == 32 { + y := (*[]uint32)(unsafe.Pointer(&x)) // #nosec G103 + return CountBitsUint32sPopCnt(*y) + } + panic("strconv.IntSize must be 32 or 64 bits") +} + +// CountBitsBytesPopCnt count 1's in x +func CountBitsBytesPopCnt(x []byte) (ret int) + +// CountBitsRunesPopCnt count 1's in x +func CountBitsRunesPopCnt(x []rune) (ret int) + +// CountBitsStringPopCnt count 1's in s +func CountBitsStringPopCnt(s string) (ret int) diff --git a/vendor/github.com/steakknife/hamming/popcount_slices_amd64.s b/vendor/github.com/steakknife/hamming/popcount_slices_amd64.s new file mode 100644 index 000000000..b6b8c7835 --- /dev/null +++ b/vendor/github.com/steakknife/hamming/popcount_slices_amd64.s @@ -0,0 +1,370 @@ +// +// hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016 Barry Allard +// +// MIT license +// + +#include "textflag.h" + +// type SliceHeader struct { +// Data uintptr 0 +// Len int 8 +// Cap int 16 +// } + +// 0 x.Data +// 8 x.Len +// 16 x.Cap +// 24 ret + +// type StringHeader struct { +// Data uintptr 0 +// Len int 8 +// } + +// 0 x.Data +// 8 x.Len +// 16 ret + +// func CountBitsInt8sPopCnt(x []int8) (ret int) +TEXT ·CountBitsInt8sPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint8sPopCnt(SB) + +// func CountBitsInt16sPopCnt(x []int16) (ret int) +TEXT ·CountBitsInt16sPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint16sPopCnt(SB) + +// func CountBitsInt32sPopCnt(x []int32) (ret int) +TEXT ·CountBitsInt32sPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint32sPopCnt(SB) + +// func CountBitsInt64sPopCnt(x []int64) (ret int) +TEXT ·CountBitsInt64sPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint64sPopCnt(SB) + +// func CountBitsUint8sPopCnt(x []uint8) (ret int) +TEXT ·CountBitsUint8sPopCnt(SB),NOSPLIT,$0 + XORQ AX, AX // ret = 0 + MOVQ x+8(FP), CX // x.Len -> CX + +test_negative_slice_len: + MOVQ CX, BX // x.Len < 0 ---> x.Len[63] != 0 + SHRQ $63, BX + JNZ done + + MOVQ x+0(FP), DI // x.Data -> DI + + CMPQ CX, $32 // x.Len >= 32 + JL unrolled_loop_skip + +unrolled_loop_setup: + XORQ R9, R9 + XORQ BX, BX + XORQ DX, DX + +unrolled_loop: // 4 unrolled loops of POPCNTQ (4 quad words at a time) + SUBQ $32, CX + + POPCNTQ 0(DI), R10 + ADDQ R10, R9 + POPCNTQ 8(DI), R11 + ADDQ R11, AX + POPCNTQ 16(DI), R12 + ADDQ R12, BX + POPCNTQ 24(DI), R13 + ADDQ R13, DX + + ADDQ $32, DI + CMPQ CX, $32 // x.Len >= 32 + JGE unrolled_loop + +unrolled_loop_done: + ADDQ R9, AX + ADDQ BX, DX + ADDQ DX, AX + + XORQ BX, BX + +unrolled_loop_skip: + CMPQ CX, $0 + JZ done + + XORQ DX, DX + +remainder_loop: + MOVB 0(DI), DL + POPCNTQ DX, BX + ADDQ BX, AX + + INCQ DI + DECQ CX + JNZ remainder_loop + +done: + MOVQ AX, ret+24(FP) + RET + +// func CountBitsUint16sPopCnt(x []uint16) (ret int) +TEXT ·CountBitsUint16sPopCnt(SB),NOSPLIT,$0 + XORQ AX, AX // ret = 0 + MOVQ x+8(FP), CX // x.Len -> CX + +test_negative_slice_len: + MOVQ CX, BX // x.Len*2 < 0 ---> x.Len[63:62] != 0 + SHLQ $1, CX + SHRQ $62, BX + JNZ done + + MOVQ x+0(FP), DI // x.Data -> DI + + + CMPQ CX, $32 // x.Len*2 >= 32 + JL unrolled_loop_skip + +unrolled_loop_setup: + XORQ R9, R9 + XORQ BX, BX + XORQ DX, DX + +unrolled_loop: // 4 unrolled loops of POPCNTQ (4 quad words at a time) + SUBQ $32, CX + + POPCNTQ 0(DI), R10 + ADDQ R10, R9 + POPCNTQ 8(DI), R11 + ADDQ R11, AX + POPCNTQ 16(DI), R12 + ADDQ R12, BX + POPCNTQ 24(DI), R13 + ADDQ R13, DX + + ADDQ $32, DI + CMPQ CX, $32 // x.Len*2 >= 32 + JGE unrolled_loop + +unrolled_loop_done: + ADDQ R9, AX + ADDQ BX, DX + ADDQ DX, AX + + XORQ BX, BX + +unrolled_loop_skip: + CMPQ CX, $0 + JZ done + + XORQ DX, DX + +remainder_loop: + MOVW 0(DI), DX + POPCNTQ DX, BX + ADDQ BX, AX + + ADDQ $2, DI + SUBQ $2, CX + JNZ remainder_loop + +done: + MOVQ AX, ret+24(FP) + RET + +// func CountBitsUint32sPopCnt(x []uint32) (ret int) +TEXT ·CountBitsUint32sPopCnt(SB),NOSPLIT,$0 + XORQ AX, AX // ret = 0 + MOVQ x+8(FP), CX // x.Len -> CX + MOVQ CX, BX + MOVQ x+0(FP), DI // x.Data -> DI + +test_negative_slice_len: + SHLQ $2, CX // x.Len*4 < 0 ---> x.Len[63:61] != 0 + SHRQ $61, BX + JNZ done + + + + CMPQ CX, $32 // x.Len*4 >= 32 + JL unrolled_loop_skip + +unrolled_loop_setup: + XORQ R9, R9 + XORQ BX, BX + XORQ DX, DX + +unrolled_loop: // 4 unrolled loops of POPCNTQ (4 quad words at a time) + SUBQ $32, CX + + POPCNTQ 0(DI), R10 // r9 += popcntq(QW DI+0) + ADDQ R10, R9 + POPCNTQ 8(DI), R11 // ax += popcntq(QW DI+8) + ADDQ R11, AX + POPCNTQ 16(DI), R12 // bx += popcntq(QW DI+16) + ADDQ R12, BX + POPCNTQ 24(DI), R13 // dx += popcntq(QW DI+24) + ADDQ R13, DX + + ADDQ $32, DI + CMPQ CX, $32 // x.Len*4 >= 32 + JGE unrolled_loop + +unrolled_loop_done: + ADDQ R9, AX // ax = (ax + r9) + (bx + dx) + ADDQ BX, DX + ADDQ DX, AX + + XORQ BX, BX + +unrolled_loop_skip: + CMPQ CX, $0 + JZ done + + XORQ DX, DX +remainder_loop: + MOVB (DI), DX // ax += popcnt(DB 0(DI)) + POPCNTQ DX, BX + ADDQ BX, AX + + INCQ DI + DECQ CX + JNZ remainder_loop + +done: + MOVQ AX, ret+24(FP) + RET + +// func CountBitsUint64sPopCnt(x []uint64) (ret int) +TEXT ·CountBitsUint64sPopCnt(SB),NOSPLIT,$0 + XORQ AX, AX // ret = 0 + MOVQ x+8(FP), CX // x.Len -> CX + +test_negative_slice_len: + MOVQ CX, BX // x.Len*8 < 0 ---> x.Len[63:60] != 0 + SHLQ $3, CX + SHRQ $60, BX + JNZ done + + MOVQ x+0(FP), DI // x.Data -> DI + + + CMPQ CX, $32 // x.Len*8 >= 32 + JL unrolled_loop_skip + +unrolled_loop_setup: + XORQ R9, R9 + XORQ BX, BX + XORQ DX, DX + +unrolled_loop: // 4 unrolled loops of POPCNTQ (4 quad words at a time) + SUBQ $32, CX + + POPCNTQ 0(DI), R10 + ADDQ R10, R9 + POPCNTQ 8(DI), R11 + ADDQ R11, AX + POPCNTQ 16(DI), R12 + ADDQ R12, BX + POPCNTQ 24(DI), R13 + ADDQ R13, DX + + ADDQ $32, DI + CMPQ CX, $32 // x.Len*4 >= 32 + JGE unrolled_loop + +unrolled_loop_done: + ADDQ R9, AX + ADDQ BX, DX + ADDQ DX, AX + + XORQ BX, BX + +unrolled_loop_skip: + CMPQ CX, $0 + JZ done + + XORQ DX, DX + +remainder_loop: + MOVQ 0(DI), DX + POPCNTQ DX, BX + ADDQ BX, AX + + ADDQ $8, DI + SUBQ $8, CX + JNZ remainder_loop + +done: + MOVQ AX, ret+24(FP) + RET + +// func CountBitsBytesPopCnt(x []byte) (ret int) +TEXT ·CountBitsBytesPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint8sPopCnt(SB) + +// func CountBitsRunesPopCnt(x []rune) (ret int) +TEXT ·CountBitsRunesPopCnt(SB),NOSPLIT,$0 + JMP ·CountBitsUint32sPopCnt(SB) + +// func CountBitsStringPopCnt(s string) (ret int) +TEXT ·CountBitsStringPopCnt(SB),NOSPLIT,$0 + XORQ AX, AX // ret = 0 + MOVQ x+8(FP), CX // x.Len -> CX + +test_negative_slice_len: + MOVQ CX, BX // x.Len < 0 ---> x.Len[63] != 0 + SHRQ $63, BX + JNZ done + + MOVQ x+0(FP), DI // x.Data -> DI + + CMPQ CX, $32 // x.Len >= 32 + JL unrolled_loop_skip + +unrolled_loop_setup: + XORQ R9, R9 + XORQ BX, BX + XORQ DX, DX + +unrolled_loop: // 4 unrolled loops of POPCNTQ (4 quad words at a time) + SUBQ $32, CX + + POPCNTQ 0(DI), R10 + ADDQ R10, R9 + POPCNTQ 8(DI), R11 + ADDQ R11, AX + POPCNTQ 16(DI), R12 + ADDQ R12, BX + POPCNTQ 24(DI), R13 + ADDQ R13, DX + + ADDQ $32, DI + CMPQ CX, $32 // x.Len >= 32 + JGE unrolled_loop + +unrolled_loop_done: + ADDQ R9, AX + ADDQ BX, DX + ADDQ DX, AX + + XORQ BX, BX + +unrolled_loop_skip: + CMPQ CX, $0 + JZ done + + XORQ DX, DX + +remainder_loop: + MOVB 0(DI), DL + POPCNTQ DX, BX + ADDQ BX, AX + + INCQ DI + DECQ CX + JNZ remainder_loop + +done: + MOVQ AX, ret+16(FP) + RET diff --git a/vendor/github.com/steakknife/hamming/slices_of_hamming.go b/vendor/github.com/steakknife/hamming/slices_of_hamming.go new file mode 100644 index 000000000..82ce948fa --- /dev/null +++ b/vendor/github.com/steakknife/hamming/slices_of_hamming.go @@ -0,0 +1,144 @@ +// +// Package hamming distance calculations in Go +// +// https://github.com/steakknife/hamming +// +// Copyright © 2014, 2015, 2016, 2018 Barry Allard +// +// MIT license +// +package hamming + +// Int8s hamming distance of two int8 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Int8s(b0, b1 []int8) int { + d := 0 + for i, x := range b0 { + d += Int8(x, b1[i]) + } + return d +} + +// Int16s hamming distance of two int16 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Int16s(b0, b1 []int16) int { + d := 0 + for i, x := range b0 { + d += Int16(x, b1[i]) + } + return d +} + +// Int32s hamming distance of two int32 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Int32s(b0, b1 []int32) int { + d := 0 + for i, x := range b0 { + d += Int32(x, b1[i]) + } + return d +} + +// Int64s hamming distance of two int64 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Int64s(b0, b1 []int64) int { + d := 0 + for i, x := range b0 { + d += Int64(x, b1[i]) + } + return d +} + +// Ints hamming distance of two int buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Ints(b0, b1 []int) int { + d := 0 + for i, x := range b0 { + d += Int(x, b1[i]) + } + return d +} + +// Uint8s hamming distance of two uint8 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Uint8s(b0, b1 []uint8) int { + d := 0 + for i, x := range b0 { + d += Uint8(x, b1[i]) + } + return d +} + +// Uint16s hamming distance of two uint16 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Uint16s(b0, b1 []uint16) int { + d := 0 + for i, x := range b0 { + d += Uint16(x, b1[i]) + } + return d +} + +// Uint32s hamming distance of two uint32 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Uint32s(b0, b1 []uint32) int { + d := 0 + for i, x := range b0 { + d += Uint32(x, b1[i]) + } + return d +} + +// Uint64s hamming distance of two uint64 buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Uint64s(b0, b1 []uint64) int { + d := 0 + for i, x := range b0 { + d += Uint64(x, b1[i]) + } + return d +} + +// Uints hamming distance of two uint buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Uints(b0, b1 []uint) int { + d := 0 + for i, x := range b0 { + d += Uint(x, b1[i]) + } + return d +} + +// Bytes hamming distance of two byte buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Bytes(b0, b1 []byte) int { + d := 0 + for i, x := range b0 { + d += Byte(x, b1[i]) + } + return d +} + +// Runes hamming distance of two rune buffers, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Runes(b0, b1 []rune) int { + d := 0 + for i, x := range b0 { + d += Rune(x, b1[i]) + } + return d +} + +// Strings hamming distance of two strings, of which the size of b0 +// is used for both (panics if b1 < b0, does not compare b1 beyond length of b0) +func Strings(b0, b1 string) int { + return Runes(runes(b0), runes(b1)) +} + +// runize string +func runes(s string) (r []rune) { + for _, ch := range s { + r = append(r, ch) + } + return +} diff --git a/vendor/github.com/tyler-smith/go-bip39/.gitignore b/vendor/github.com/tyler-smith/go-bip39/.gitignore new file mode 100644 index 000000000..0f49594a0 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/.gitignore @@ -0,0 +1,56 @@ +# Executable from build +go-bip39 + + +# Dev utils +.ackrc + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +coverage.out +*.o +*.a +*.so +*.db + +# Temp files +*~ +*.kate-swp +*.orig +debug +*.txt +*.log +.vscode/ +.idea/ +peers.json +*.csv +*.gz + +# Folders +_obj +_test +bin +pkg +.vagrant + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.block +*.entry + +.DS_Store + +*.out +.idea/ +----* diff --git a/vendor/github.com/tyler-smith/go-bip39/.golangci.yml b/vendor/github.com/tyler-smith/go-bip39/.golangci.yml new file mode 100644 index 000000000..823061d3a --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/.golangci.yml @@ -0,0 +1,44 @@ +issues: + max-per-linter: 999999 + max-same: 999999 + +linters-settings: + errcheck: + check-type-assertions: true + check-blank: true + nakedret: + max-func-lines: 0 + misspell: + locale: US + dupl: + threshold: 50 + goconst: + min-occurrences: 2 + gocyclo: + min-complexity: 8 + lll: + line-length: 250 + +linters: + enable: + - gofmt + - golint + - goimports + - unconvert + - ineffassign + - staticcheck + - structcheck + - unused + - unparam + - varcheck + - deadcode + - gosimple + - dupl + - gocyclo + - nakedret + - lll + - goconst + - govet + - megacheck + - errcheck + - prealloc diff --git a/vendor/github.com/tyler-smith/go-bip39/.travis.yml b/vendor/github.com/tyler-smith/go-bip39/.travis.yml new file mode 100644 index 000000000..d8af78aac --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/.travis.yml @@ -0,0 +1,18 @@ +language: go +go: + - "1.6.x" + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + - "1.12.x" + - "release" + - "tip" + +before_install: + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.10 + +script: + - $GOPATH/bin/golangci-lint run + - make profile_tests diff --git a/vendor/github.com/tyler-smith/go-bip39/Gopkg.lock b/vendor/github.com/tyler-smith/go-bip39/Gopkg.lock new file mode 100644 index 000000000..e15d33f31 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["pbkdf2"] + revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "d7f1a7207c39125afcb9ca2365832cb83458edfc17f2f7e8d28fd56f19436856" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/tyler-smith/go-bip39/Gopkg.toml b/vendor/github.com/tyler-smith/go-bip39/Gopkg.toml new file mode 100644 index 000000000..2f655b2c7 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/Gopkg.toml @@ -0,0 +1,26 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + branch = "master" + name = "golang.org/x/crypto" diff --git a/vendor/github.com/tyler-smith/go-bip39/LICENSE b/vendor/github.com/tyler-smith/go-bip39/LICENSE new file mode 100644 index 000000000..4dae82d35 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2018 Tyler Smith and contributors + +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/tyler-smith/go-bip39/Makefile b/vendor/github.com/tyler-smith/go-bip39/Makefile new file mode 100644 index 000000000..f0f3fe88c --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/Makefile @@ -0,0 +1,11 @@ +.DEFAULT_GOAL := help + +tests: ## Run tests with coverage + go test -v -cover ./... + +profile_tests: ## Run tests and output coverage profiling + go test -v -coverprofile=coverage.out . + go tool cover -html=coverage.out + +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/vendor/github.com/tyler-smith/go-bip39/README.md b/vendor/github.com/tyler-smith/go-bip39/README.md new file mode 100644 index 000000000..933296fd8 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/README.md @@ -0,0 +1,45 @@ +# go-bip39 +[![Build Status](https://travis-ci.org/tyler-smith/go-bip39.svg?branch=master)](https://travis-ci.org/tyler-smith/go-bip39) +[![license](https://img.shields.io/github/license/tyler-smith/go-bip39.svg?maxAge=2592000)](https://github.com/tyler-smith/go-bip39/blob/master/LICENSE) +[![Documentation](https://godoc.org/github.com/tyler-smith/go-bip39?status.svg)](http://godoc.org/github.com/tyler-smith/go-bip39) +[![Go Report Card](https://goreportcard.com/badge/github.com/tyler-smith/go-bip39)](https://goreportcard.com/report/github.com/tyler-smith/go-bip39) +[![GitHub issues](https://img.shields.io/github/issues/tyler-smith/go-bip39.svg)](https://github.com/tyler-smith/go-bip39/issues) + + +A golang implementation of the BIP0039 spec for mnemonic seeds + +## Example + +```go +package main + +import ( + "github.com/tyler-smith/go-bip39" + "github.com/tyler-smith/go-bip32" + "fmt" +) + +func main(){ + // Generate a mnemonic for memorization or user-friendly seeds + entropy, _ := bip39.NewEntropy(256) + mnemonic, _ := bip39.NewMnemonic(entropy) + + // Generate a Bip32 HD wallet for the mnemonic and a user supplied password + seed := bip39.NewSeed(mnemonic, "Secret Passphrase") + + masterKey, _ := bip32.NewMasterKey(seed) + publicKey := masterKey.PublicKey() + + // Display mnemonic and keys + fmt.Println("Mnemonic: ", mnemonic) + fmt.Println("Master private key: ", masterKey) + fmt.Println("Master public key: ", publicKey) +} +``` + +## Credits + +Wordlists are from the [bip39 spec](https://github.com/bitcoin/bips/tree/master/bip-0039). + +Test vectors are from the standard Python BIP0039 implementation from the +Trezor team: [https://github.com/trezor/python-mnemonic](https://github.com/trezor/python-mnemonic) diff --git a/vendor/github.com/tyler-smith/go-bip39/bip39.go b/vendor/github.com/tyler-smith/go-bip39/bip39.go new file mode 100644 index 000000000..72b4d0c49 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/bip39.go @@ -0,0 +1,396 @@ +// Package bip39 is the Golang implementation of the BIP39 spec. +// +// The official BIP39 spec can be found at +// https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki +package bip39 + +import ( + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "encoding/binary" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/tyler-smith/go-bip39/wordlists" + "golang.org/x/crypto/pbkdf2" +) + +var ( + // Some bitwise operands for working with big.Ints + last11BitsMask = big.NewInt(2047) + shift11BitsMask = big.NewInt(2048) + bigOne = big.NewInt(1) + bigTwo = big.NewInt(2) + + // used to isolate the checksum bits from the entropy+checksum byte array + wordLengthChecksumMasksMapping = map[int]*big.Int{ + 12: big.NewInt(15), + 15: big.NewInt(31), + 18: big.NewInt(63), + 21: big.NewInt(127), + 24: big.NewInt(255), + } + // used to use only the desired x of 8 available checksum bits. + // 256 bit (word length 24) requires all 8 bits of the checksum, + // and thus no shifting is needed for it (we would get a divByZero crash if we did) + wordLengthChecksumShiftMapping = map[int]*big.Int{ + 12: big.NewInt(16), + 15: big.NewInt(8), + 18: big.NewInt(4), + 21: big.NewInt(2), + } + + // wordList is the set of words to use + wordList []string + + // wordMap is a reverse lookup map for wordList + wordMap map[string]int +) + +var ( + // ErrInvalidMnemonic is returned when trying to use a malformed mnemonic. + ErrInvalidMnemonic = errors.New("Invalid mnenomic") + + // ErrEntropyLengthInvalid is returned when trying to use an entropy set with + // an invalid size. + ErrEntropyLengthInvalid = errors.New("Entropy length must be [128, 256] and a multiple of 32") + + // ErrValidatedSeedLengthMismatch is returned when a validated seed is not the + // same size as the given seed. This should never happen is present only as a + // sanity assertion. + ErrValidatedSeedLengthMismatch = errors.New("Seed length does not match validated seed length") + + // ErrChecksumIncorrect is returned when entropy has the incorrect checksum. + ErrChecksumIncorrect = errors.New("Checksum incorrect") +) + +func init() { + SetWordList(wordlists.English) +} + +// SetWordList sets the list of words to use for mnemonics. Currently the list +// that is set is used package-wide. +func SetWordList(list []string) { + wordList = list + wordMap = map[string]int{} + for i, v := range wordList { + wordMap[v] = i + } +} + +// GetWordList gets the list of words to use for mnemonics. +func GetWordList() []string { + return wordList +} + +// GetWordIndex gets word index in wordMap. +func GetWordIndex(word string) (int, bool) { + idx, ok := wordMap[word] + return idx, ok +} + +// NewEntropy will create random entropy bytes +// so long as the requested size bitSize is an appropriate size. +// +// bitSize has to be a multiple 32 and be within the inclusive range of {128, 256} +func NewEntropy(bitSize int) ([]byte, error) { + err := validateEntropyBitSize(bitSize) + if err != nil { + return nil, err + } + + entropy := make([]byte, bitSize/8) + _, err = rand.Read(entropy) + return entropy, err +} + +// EntropyFromMnemonic takes a mnemonic generated by this library, +// and returns the input entropy used to generate the given mnemonic. +// An error is returned if the given mnemonic is invalid. +func EntropyFromMnemonic(mnemonic string) ([]byte, error) { + mnemonicSlice, isValid := splitMnemonicWords(mnemonic) + if !isValid { + return nil, ErrInvalidMnemonic + } + + // Decode the words into a big.Int. + b := big.NewInt(0) + for _, v := range mnemonicSlice { + index, ok := wordMap[v] + if !ok { + return nil, fmt.Errorf("word `%v` not found in reverse map", v) + } + var wordBytes [2]byte + binary.BigEndian.PutUint16(wordBytes[:], uint16(index)) + b = b.Mul(b, shift11BitsMask) + b = b.Or(b, big.NewInt(0).SetBytes(wordBytes[:])) + } + + // Build and add the checksum to the big.Int. + checksum := big.NewInt(0) + checksumMask := wordLengthChecksumMasksMapping[len(mnemonicSlice)] + checksum = checksum.And(b, checksumMask) + + b.Div(b, big.NewInt(0).Add(checksumMask, bigOne)) + + // The entropy is the underlying bytes of the big.Int. Any upper bytes of + // all 0's are not returned so we pad the beginning of the slice with empty + // bytes if necessary. + entropy := b.Bytes() + entropy = padByteSlice(entropy, len(mnemonicSlice)/3*4) + + // Generate the checksum and compare with the one we got from the mneomnic. + entropyChecksumBytes, err := computeChecksum(entropy) + if err != nil { + return nil, err + } + + entropyChecksum := big.NewInt(int64(entropyChecksumBytes[0])) + if l := len(mnemonicSlice); l != 24 { + checksumShift := wordLengthChecksumShiftMapping[l] + entropyChecksum.Div(entropyChecksum, checksumShift) + } + + if checksum.Cmp(entropyChecksum) != 0 { + return nil, ErrChecksumIncorrect + } + + return entropy, nil +} + +// NewMnemonic will return a string consisting of the mnemonic words for +// the given entropy. +// If the provide entropy is invalid, an error will be returned. +func NewMnemonic(entropy []byte) (string, error) { + // Compute some lengths for convenience. + entropyBitLength := len(entropy) * 8 + checksumBitLength := entropyBitLength / 32 + sentenceLength := (entropyBitLength + checksumBitLength) / 11 + + // Validate that the requested size is supported. + err := validateEntropyBitSize(entropyBitLength) + if err != nil { + return "", err + } + + // Add checksum to entropy. + entropy, err = addChecksum(entropy) + if err != nil { + return "", err + } + + // Break entropy up into sentenceLength chunks of 11 bits. + // For each word AND mask the rightmost 11 bits and find the word at that index. + // Then bitshift entropy 11 bits right and repeat. + // Add to the last empty slot so we can work with LSBs instead of MSB. + + // Entropy as an int so we can bitmask without worrying about bytes slices. + entropyInt := new(big.Int).SetBytes(entropy) + + // Slice to hold words in. + words := make([]string, sentenceLength) + + // Throw away big.Int for AND masking. + word := big.NewInt(0) + + for i := sentenceLength - 1; i >= 0; i-- { + // Get 11 right most bits and bitshift 11 to the right for next time. + word.And(entropyInt, last11BitsMask) + entropyInt.Div(entropyInt, shift11BitsMask) + + // Get the bytes representing the 11 bits as a 2 byte slice. + wordBytes := padByteSlice(word.Bytes(), 2) + + // Convert bytes to an index and add that word to the list. + words[i] = wordList[binary.BigEndian.Uint16(wordBytes)] + } + + return strings.Join(words, " "), nil +} + +// MnemonicToByteArray takes a mnemonic string and turns it into a byte array +// suitable for creating another mnemonic. +// An error is returned if the mnemonic is invalid. +func MnemonicToByteArray(mnemonic string, raw ...bool) ([]byte, error) { + var ( + mnemonicSlice = strings.Split(mnemonic, " ") + entropyBitSize = len(mnemonicSlice) * 11 + checksumBitSize = entropyBitSize % 32 + fullByteSize = (entropyBitSize-checksumBitSize)/8 + 1 + checksumByteSize = fullByteSize - (fullByteSize % 4) + ) + + // Pre validate that the mnemonic is well formed and only contains words that + // are present in the word list. + if !IsMnemonicValid(mnemonic) { + return nil, ErrInvalidMnemonic + } + + // Convert word indices to a big.Int representing the entropy. + checksummedEntropy := big.NewInt(0) + modulo := big.NewInt(2048) + for _, v := range mnemonicSlice { + index := big.NewInt(int64(wordMap[v])) + checksummedEntropy.Mul(checksummedEntropy, modulo) + checksummedEntropy.Add(checksummedEntropy, index) + } + + // Calculate the unchecksummed entropy so we can validate that the checksum is + // correct. + checksumModulo := big.NewInt(0).Exp(bigTwo, big.NewInt(int64(checksumBitSize)), nil) + rawEntropy := big.NewInt(0).Div(checksummedEntropy, checksumModulo) + + // Convert big.Ints to byte padded byte slices. + rawEntropyBytes := padByteSlice(rawEntropy.Bytes(), checksumByteSize) + checksummedEntropyBytes := padByteSlice(checksummedEntropy.Bytes(), fullByteSize) + + // Validate that the checksum is correct. + unpaddedChecksumedBytes, err := addChecksum(rawEntropyBytes) + if err != nil { + return nil, err + } + + newChecksummedEntropyBytes := padByteSlice(unpaddedChecksumedBytes, fullByteSize) + if !compareByteSlices(checksummedEntropyBytes, newChecksummedEntropyBytes) { + return nil, ErrChecksumIncorrect + } + + if len(raw) > 0 && raw[0] { + return rawEntropyBytes, nil + } + + return checksummedEntropyBytes, nil +} + +// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password. +// An error is returned if the mnemonic is not convertible to a byte array. +func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) { + _, err := MnemonicToByteArray(mnemonic) + if err != nil { + return nil, err + } + return NewSeed(mnemonic, password), nil +} + +// NewSeed creates a hashed seed output given a provided string and password. +// No checking is performed to validate that the string provided is a valid mnemonic. +func NewSeed(mnemonic string, password string) []byte { + return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New) +} + +// IsMnemonicValid attempts to verify that the provided mnemonic is valid. +// Validity is determined by both the number of words being appropriate, +// and that all the words in the mnemonic are present in the word list. +func IsMnemonicValid(mnemonic string) bool { + // Create a list of all the words in the mnemonic sentence + words := strings.Fields(mnemonic) + + // Get word count + wordCount := len(words) + + // The number of words should be 12, 15, 18, 21 or 24 + if wordCount%3 != 0 || wordCount < 12 || wordCount > 24 { + return false + } + + // Check if all words belong in the wordlist + for _, word := range words { + if _, ok := wordMap[word]; !ok { + return false + } + } + + return true +} + +// Appends to data the first (len(data) / 32)bits of the result of sha256(data) +// Currently only supports data up to 32 bytes +func addChecksum(data []byte) ([]byte, error) { + // Get first byte of sha256 + hash, err := computeChecksum(data) + if err != nil { + return nil, err + } + + firstChecksumByte := hash[0] + + // len() is in bytes so we divide by 4 + checksumBitLength := uint(len(data) / 4) + + // For each bit of check sum we want we shift the data one the left + // and then set the (new) right most bit equal to checksum bit at that index + // staring from the left + dataBigInt := new(big.Int).SetBytes(data) + for i := uint(0); i < checksumBitLength; i++ { + // Bitshift 1 left + dataBigInt.Mul(dataBigInt, bigTwo) + + // Set rightmost bit if leftmost checksum bit is set + if firstChecksumByte&(1<<(7-i)) > 0 { + dataBigInt.Or(dataBigInt, bigOne) + } + } + + return dataBigInt.Bytes(), nil +} + +func computeChecksum(data []byte) ([]byte, error) { + hasher := sha256.New() + _, err := hasher.Write(data) + if err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// validateEntropyBitSize ensures that entropy is the correct size for being a +// mnemonic. +func validateEntropyBitSize(bitSize int) error { + if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 { + return ErrEntropyLengthInvalid + } + return nil +} + +// padByteSlice returns a byte slice of the given size with contents of the +// given slice left padded and any empty spaces filled with 0's. +func padByteSlice(slice []byte, length int) []byte { + offset := length - len(slice) + if offset <= 0 { + return slice + } + newSlice := make([]byte, length) + copy(newSlice[offset:], slice) + return newSlice +} + +// compareByteSlices returns true of the byte slices have equal contents and +// returns false otherwise. +func compareByteSlices(a, b []byte) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +func splitMnemonicWords(mnemonic string) ([]string, bool) { + // Create a list of all the words in the mnemonic sentence + words := strings.Fields(mnemonic) + + // Get num of words + numOfWords := len(words) + + // The number of words should be 12, 15, 18, 21 or 24 + if numOfWords%3 != 0 || numOfWords < 12 || numOfWords > 24 { + return nil, false + } + return words, true +} diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_simplified.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_simplified.go new file mode 100644 index 000000000..0ee297270 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_simplified.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/chinese_simplified.txt + // $ crc32 chinese_simplified.txt + // e3721bbf + checksum := crc32.ChecksumIEEE([]byte(chineseSimplified)) + if fmt.Sprintf("%x", checksum) != "e3721bbf" { + panic("chineseSimplified checksum invalid") + } +} + +// ChineseSimplified is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/chinese_simplified.txt +var ChineseSimplified = strings.Split(strings.TrimSpace(chineseSimplified), "\n") +var chineseSimplified = `的 +一 +是 +在 +不 +了 +有 +和 +人 +这 +中 +大 +为 +上 +个 +国 +我 +以 +要 +他 +时 +来 +用 +们 +生 +到 +作 +地 +于 +出 +就 +分 +对 +成 +会 +可 +主 +发 +年 +动 +同 +工 +也 +能 +下 +过 +子 +说 +产 +种 +面 +而 +方 +后 +多 +定 +行 +学 +法 +所 +民 +得 +经 +十 +三 +之 +进 +着 +等 +部 +度 +家 +电 +力 +里 +如 +水 +化 +高 +自 +二 +理 +起 +小 +物 +现 +实 +加 +量 +都 +两 +体 +制 +机 +当 +使 +点 +从 +业 +本 +去 +把 +性 +好 +应 +开 +它 +合 +还 +因 +由 +其 +些 +然 +前 +外 +天 +政 +四 +日 +那 +社 +义 +事 +平 +形 +相 +全 +表 +间 +样 +与 +关 +各 +重 +新 +线 +内 +数 +正 +心 +反 +你 +明 +看 +原 +又 +么 +利 +比 +或 +但 +质 +气 +第 +向 +道 +命 +此 +变 +条 +只 +没 +结 +解 +问 +意 +建 +月 +公 +无 +系 +军 +很 +情 +者 +最 +立 +代 +想 +已 +通 +并 +提 +直 +题 +党 +程 +展 +五 +果 +料 +象 +员 +革 +位 +入 +常 +文 +总 +次 +品 +式 +活 +设 +及 +管 +特 +件 +长 +求 +老 +头 +基 +资 +边 +流 +路 +级 +少 +图 +山 +统 +接 +知 +较 +将 +组 +见 +计 +别 +她 +手 +角 +期 +根 +论 +运 +农 +指 +几 +九 +区 +强 +放 +决 +西 +被 +干 +做 +必 +战 +先 +回 +则 +任 +取 +据 +处 +队 +南 +给 +色 +光 +门 +即 +保 +治 +北 +造 +百 +规 +热 +领 +七 +海 +口 +东 +导 +器 +压 +志 +世 +金 +增 +争 +济 +阶 +油 +思 +术 +极 +交 +受 +联 +什 +认 +六 +共 +权 +收 +证 +改 +清 +美 +再 +采 +转 +更 +单 +风 +切 +打 +白 +教 +速 +花 +带 +安 +场 +身 +车 +例 +真 +务 +具 +万 +每 +目 +至 +达 +走 +积 +示 +议 +声 +报 +斗 +完 +类 +八 +离 +华 +名 +确 +才 +科 +张 +信 +马 +节 +话 +米 +整 +空 +元 +况 +今 +集 +温 +传 +土 +许 +步 +群 +广 +石 +记 +需 +段 +研 +界 +拉 +林 +律 +叫 +且 +究 +观 +越 +织 +装 +影 +算 +低 +持 +音 +众 +书 +布 +复 +容 +儿 +须 +际 +商 +非 +验 +连 +断 +深 +难 +近 +矿 +千 +周 +委 +素 +技 +备 +半 +办 +青 +省 +列 +习 +响 +约 +支 +般 +史 +感 +劳 +便 +团 +往 +酸 +历 +市 +克 +何 +除 +消 +构 +府 +称 +太 +准 +精 +值 +号 +率 +族 +维 +划 +选 +标 +写 +存 +候 +毛 +亲 +快 +效 +斯 +院 +查 +江 +型 +眼 +王 +按 +格 +养 +易 +置 +派 +层 +片 +始 +却 +专 +状 +育 +厂 +京 +识 +适 +属 +圆 +包 +火 +住 +调 +满 +县 +局 +照 +参 +红 +细 +引 +听 +该 +铁 +价 +严 +首 +底 +液 +官 +德 +随 +病 +苏 +失 +尔 +死 +讲 +配 +女 +黄 +推 +显 +谈 +罪 +神 +艺 +呢 +席 +含 +企 +望 +密 +批 +营 +项 +防 +举 +球 +英 +氧 +势 +告 +李 +台 +落 +木 +帮 +轮 +破 +亚 +师 +围 +注 +远 +字 +材 +排 +供 +河 +态 +封 +另 +施 +减 +树 +溶 +怎 +止 +案 +言 +士 +均 +武 +固 +叶 +鱼 +波 +视 +仅 +费 +紧 +爱 +左 +章 +早 +朝 +害 +续 +轻 +服 +试 +食 +充 +兵 +源 +判 +护 +司 +足 +某 +练 +差 +致 +板 +田 +降 +黑 +犯 +负 +击 +范 +继 +兴 +似 +余 +坚 +曲 +输 +修 +故 +城 +夫 +够 +送 +笔 +船 +占 +右 +财 +吃 +富 +春 +职 +觉 +汉 +画 +功 +巴 +跟 +虽 +杂 +飞 +检 +吸 +助 +升 +阳 +互 +初 +创 +抗 +考 +投 +坏 +策 +古 +径 +换 +未 +跑 +留 +钢 +曾 +端 +责 +站 +简 +述 +钱 +副 +尽 +帝 +射 +草 +冲 +承 +独 +令 +限 +阿 +宣 +环 +双 +请 +超 +微 +让 +控 +州 +良 +轴 +找 +否 +纪 +益 +依 +优 +顶 +础 +载 +倒 +房 +突 +坐 +粉 +敌 +略 +客 +袁 +冷 +胜 +绝 +析 +块 +剂 +测 +丝 +协 +诉 +念 +陈 +仍 +罗 +盐 +友 +洋 +错 +苦 +夜 +刑 +移 +频 +逐 +靠 +混 +母 +短 +皮 +终 +聚 +汽 +村 +云 +哪 +既 +距 +卫 +停 +烈 +央 +察 +烧 +迅 +境 +若 +印 +洲 +刻 +括 +激 +孔 +搞 +甚 +室 +待 +核 +校 +散 +侵 +吧 +甲 +游 +久 +菜 +味 +旧 +模 +湖 +货 +损 +预 +阻 +毫 +普 +稳 +乙 +妈 +植 +息 +扩 +银 +语 +挥 +酒 +守 +拿 +序 +纸 +医 +缺 +雨 +吗 +针 +刘 +啊 +急 +唱 +误 +训 +愿 +审 +附 +获 +茶 +鲜 +粮 +斤 +孩 +脱 +硫 +肥 +善 +龙 +演 +父 +渐 +血 +欢 +械 +掌 +歌 +沙 +刚 +攻 +谓 +盾 +讨 +晚 +粒 +乱 +燃 +矛 +乎 +杀 +药 +宁 +鲁 +贵 +钟 +煤 +读 +班 +伯 +香 +介 +迫 +句 +丰 +培 +握 +兰 +担 +弦 +蛋 +沉 +假 +穿 +执 +答 +乐 +谁 +顺 +烟 +缩 +征 +脸 +喜 +松 +脚 +困 +异 +免 +背 +星 +福 +买 +染 +井 +概 +慢 +怕 +磁 +倍 +祖 +皇 +促 +静 +补 +评 +翻 +肉 +践 +尼 +衣 +宽 +扬 +棉 +希 +伤 +操 +垂 +秋 +宜 +氢 +套 +督 +振 +架 +亮 +末 +宪 +庆 +编 +牛 +触 +映 +雷 +销 +诗 +座 +居 +抓 +裂 +胞 +呼 +娘 +景 +威 +绿 +晶 +厚 +盟 +衡 +鸡 +孙 +延 +危 +胶 +屋 +乡 +临 +陆 +顾 +掉 +呀 +灯 +岁 +措 +束 +耐 +剧 +玉 +赵 +跳 +哥 +季 +课 +凯 +胡 +额 +款 +绍 +卷 +齐 +伟 +蒸 +殖 +永 +宗 +苗 +川 +炉 +岩 +弱 +零 +杨 +奏 +沿 +露 +杆 +探 +滑 +镇 +饭 +浓 +航 +怀 +赶 +库 +夺 +伊 +灵 +税 +途 +灭 +赛 +归 +召 +鼓 +播 +盘 +裁 +险 +康 +唯 +录 +菌 +纯 +借 +糖 +盖 +横 +符 +私 +努 +堂 +域 +枪 +润 +幅 +哈 +竟 +熟 +虫 +泽 +脑 +壤 +碳 +欧 +遍 +侧 +寨 +敢 +彻 +虑 +斜 +薄 +庭 +纳 +弹 +饲 +伸 +折 +麦 +湿 +暗 +荷 +瓦 +塞 +床 +筑 +恶 +户 +访 +塔 +奇 +透 +梁 +刀 +旋 +迹 +卡 +氯 +遇 +份 +毒 +泥 +退 +洗 +摆 +灰 +彩 +卖 +耗 +夏 +择 +忙 +铜 +献 +硬 +予 +繁 +圈 +雪 +函 +亦 +抽 +篇 +阵 +阴 +丁 +尺 +追 +堆 +雄 +迎 +泛 +爸 +楼 +避 +谋 +吨 +野 +猪 +旗 +累 +偏 +典 +馆 +索 +秦 +脂 +潮 +爷 +豆 +忽 +托 +惊 +塑 +遗 +愈 +朱 +替 +纤 +粗 +倾 +尚 +痛 +楚 +谢 +奋 +购 +磨 +君 +池 +旁 +碎 +骨 +监 +捕 +弟 +暴 +割 +贯 +殊 +释 +词 +亡 +壁 +顿 +宝 +午 +尘 +闻 +揭 +炮 +残 +冬 +桥 +妇 +警 +综 +招 +吴 +付 +浮 +遭 +徐 +您 +摇 +谷 +赞 +箱 +隔 +订 +男 +吹 +园 +纷 +唐 +败 +宋 +玻 +巨 +耕 +坦 +荣 +闭 +湾 +键 +凡 +驻 +锅 +救 +恩 +剥 +凝 +碱 +齿 +截 +炼 +麻 +纺 +禁 +废 +盛 +版 +缓 +净 +睛 +昌 +婚 +涉 +筒 +嘴 +插 +岸 +朗 +庄 +街 +藏 +姑 +贸 +腐 +奴 +啦 +惯 +乘 +伙 +恢 +匀 +纱 +扎 +辩 +耳 +彪 +臣 +亿 +璃 +抵 +脉 +秀 +萨 +俄 +网 +舞 +店 +喷 +纵 +寸 +汗 +挂 +洪 +贺 +闪 +柬 +爆 +烯 +津 +稻 +墙 +软 +勇 +像 +滚 +厘 +蒙 +芳 +肯 +坡 +柱 +荡 +腿 +仪 +旅 +尾 +轧 +冰 +贡 +登 +黎 +削 +钻 +勒 +逃 +障 +氨 +郭 +峰 +币 +港 +伏 +轨 +亩 +毕 +擦 +莫 +刺 +浪 +秘 +援 +株 +健 +售 +股 +岛 +甘 +泡 +睡 +童 +铸 +汤 +阀 +休 +汇 +舍 +牧 +绕 +炸 +哲 +磷 +绩 +朋 +淡 +尖 +启 +陷 +柴 +呈 +徒 +颜 +泪 +稍 +忘 +泵 +蓝 +拖 +洞 +授 +镜 +辛 +壮 +锋 +贫 +虚 +弯 +摩 +泰 +幼 +廷 +尊 +窗 +纲 +弄 +隶 +疑 +氏 +宫 +姐 +震 +瑞 +怪 +尤 +琴 +循 +描 +膜 +违 +夹 +腰 +缘 +珠 +穷 +森 +枝 +竹 +沟 +催 +绳 +忆 +邦 +剩 +幸 +浆 +栏 +拥 +牙 +贮 +礼 +滤 +钠 +纹 +罢 +拍 +咱 +喊 +袖 +埃 +勤 +罚 +焦 +潜 +伍 +墨 +欲 +缝 +姓 +刊 +饱 +仿 +奖 +铝 +鬼 +丽 +跨 +默 +挖 +链 +扫 +喝 +袋 +炭 +污 +幕 +诸 +弧 +励 +梅 +奶 +洁 +灾 +舟 +鉴 +苯 +讼 +抱 +毁 +懂 +寒 +智 +埔 +寄 +届 +跃 +渡 +挑 +丹 +艰 +贝 +碰 +拔 +爹 +戴 +码 +梦 +芽 +熔 +赤 +渔 +哭 +敬 +颗 +奔 +铅 +仲 +虎 +稀 +妹 +乏 +珍 +申 +桌 +遵 +允 +隆 +螺 +仓 +魏 +锐 +晓 +氮 +兼 +隐 +碍 +赫 +拨 +忠 +肃 +缸 +牵 +抢 +博 +巧 +壳 +兄 +杜 +讯 +诚 +碧 +祥 +柯 +页 +巡 +矩 +悲 +灌 +龄 +伦 +票 +寻 +桂 +铺 +圣 +恐 +恰 +郑 +趣 +抬 +荒 +腾 +贴 +柔 +滴 +猛 +阔 +辆 +妻 +填 +撤 +储 +签 +闹 +扰 +紫 +砂 +递 +戏 +吊 +陶 +伐 +喂 +疗 +瓶 +婆 +抚 +臂 +摸 +忍 +虾 +蜡 +邻 +胸 +巩 +挤 +偶 +弃 +槽 +劲 +乳 +邓 +吉 +仁 +烂 +砖 +租 +乌 +舰 +伴 +瓜 +浅 +丙 +暂 +燥 +橡 +柳 +迷 +暖 +牌 +秧 +胆 +详 +簧 +踏 +瓷 +谱 +呆 +宾 +糊 +洛 +辉 +愤 +竞 +隙 +怒 +粘 +乃 +绪 +肩 +籍 +敏 +涂 +熙 +皆 +侦 +悬 +掘 +享 +纠 +醒 +狂 +锁 +淀 +恨 +牲 +霸 +爬 +赏 +逆 +玩 +陵 +祝 +秒 +浙 +貌 +役 +彼 +悉 +鸭 +趋 +凤 +晨 +畜 +辈 +秩 +卵 +署 +梯 +炎 +滩 +棋 +驱 +筛 +峡 +冒 +啥 +寿 +译 +浸 +泉 +帽 +迟 +硅 +疆 +贷 +漏 +稿 +冠 +嫩 +胁 +芯 +牢 +叛 +蚀 +奥 +鸣 +岭 +羊 +凭 +串 +塘 +绘 +酵 +融 +盆 +锡 +庙 +筹 +冻 +辅 +摄 +袭 +筋 +拒 +僚 +旱 +钾 +鸟 +漆 +沈 +眉 +疏 +添 +棒 +穗 +硝 +韩 +逼 +扭 +侨 +凉 +挺 +碗 +栽 +炒 +杯 +患 +馏 +劝 +豪 +辽 +勃 +鸿 +旦 +吏 +拜 +狗 +埋 +辊 +掩 +饮 +搬 +骂 +辞 +勾 +扣 +估 +蒋 +绒 +雾 +丈 +朵 +姆 +拟 +宇 +辑 +陕 +雕 +偿 +蓄 +崇 +剪 +倡 +厅 +咬 +驶 +薯 +刷 +斥 +番 +赋 +奉 +佛 +浇 +漫 +曼 +扇 +钙 +桃 +扶 +仔 +返 +俗 +亏 +腔 +鞋 +棱 +覆 +框 +悄 +叔 +撞 +骗 +勘 +旺 +沸 +孤 +吐 +孟 +渠 +屈 +疾 +妙 +惜 +仰 +狠 +胀 +谐 +抛 +霉 +桑 +岗 +嘛 +衰 +盗 +渗 +脏 +赖 +涌 +甜 +曹 +阅 +肌 +哩 +厉 +烃 +纬 +毅 +昨 +伪 +症 +煮 +叹 +钉 +搭 +茎 +笼 +酷 +偷 +弓 +锥 +恒 +杰 +坑 +鼻 +翼 +纶 +叙 +狱 +逮 +罐 +络 +棚 +抑 +膨 +蔬 +寺 +骤 +穆 +冶 +枯 +册 +尸 +凸 +绅 +坯 +牺 +焰 +轰 +欣 +晋 +瘦 +御 +锭 +锦 +丧 +旬 +锻 +垄 +搜 +扑 +邀 +亭 +酯 +迈 +舒 +脆 +酶 +闲 +忧 +酚 +顽 +羽 +涨 +卸 +仗 +陪 +辟 +惩 +杭 +姚 +肚 +捉 +飘 +漂 +昆 +欺 +吾 +郎 +烷 +汁 +呵 +饰 +萧 +雅 +邮 +迁 +燕 +撒 +姻 +赴 +宴 +烦 +债 +帐 +斑 +铃 +旨 +醇 +董 +饼 +雏 +姿 +拌 +傅 +腹 +妥 +揉 +贤 +拆 +歪 +葡 +胺 +丢 +浩 +徽 +昂 +垫 +挡 +览 +贪 +慰 +缴 +汪 +慌 +冯 +诺 +姜 +谊 +凶 +劣 +诬 +耀 +昏 +躺 +盈 +骑 +乔 +溪 +丛 +卢 +抹 +闷 +咨 +刮 +驾 +缆 +悟 +摘 +铒 +掷 +颇 +幻 +柄 +惠 +惨 +佳 +仇 +腊 +窝 +涤 +剑 +瞧 +堡 +泼 +葱 +罩 +霍 +捞 +胎 +苍 +滨 +俩 +捅 +湘 +砍 +霞 +邵 +萄 +疯 +淮 +遂 +熊 +粪 +烘 +宿 +档 +戈 +驳 +嫂 +裕 +徙 +箭 +捐 +肠 +撑 +晒 +辨 +殿 +莲 +摊 +搅 +酱 +屏 +疫 +哀 +蔡 +堵 +沫 +皱 +畅 +叠 +阁 +莱 +敲 +辖 +钩 +痕 +坝 +巷 +饿 +祸 +丘 +玄 +溜 +曰 +逻 +彭 +尝 +卿 +妨 +艇 +吞 +韦 +怨 +矮 +歇 +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_traditional.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_traditional.go new file mode 100644 index 000000000..83812cee5 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/chinese_traditional.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/chinese_traditional.txt + // $ crc32 chinese_traditional.txt + // 3c20b443 + checksum := crc32.ChecksumIEEE([]byte(chineseTraditional)) + if fmt.Sprintf("%x", checksum) != "3c20b443" { + panic("chineseTraditional checksum invalid") + } +} + +// ChineseTraditional is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/chinese_traditional.txt +var ChineseTraditional = strings.Split(strings.TrimSpace(chineseTraditional), "\n") +var chineseTraditional = `的 +一 +是 +在 +不 +了 +有 +和 +人 +這 +中 +大 +為 +上 +個 +國 +我 +以 +要 +他 +時 +來 +用 +們 +生 +到 +作 +地 +於 +出 +就 +分 +對 +成 +會 +可 +主 +發 +年 +動 +同 +工 +也 +能 +下 +過 +子 +說 +產 +種 +面 +而 +方 +後 +多 +定 +行 +學 +法 +所 +民 +得 +經 +十 +三 +之 +進 +著 +等 +部 +度 +家 +電 +力 +裡 +如 +水 +化 +高 +自 +二 +理 +起 +小 +物 +現 +實 +加 +量 +都 +兩 +體 +制 +機 +當 +使 +點 +從 +業 +本 +去 +把 +性 +好 +應 +開 +它 +合 +還 +因 +由 +其 +些 +然 +前 +外 +天 +政 +四 +日 +那 +社 +義 +事 +平 +形 +相 +全 +表 +間 +樣 +與 +關 +各 +重 +新 +線 +內 +數 +正 +心 +反 +你 +明 +看 +原 +又 +麼 +利 +比 +或 +但 +質 +氣 +第 +向 +道 +命 +此 +變 +條 +只 +沒 +結 +解 +問 +意 +建 +月 +公 +無 +系 +軍 +很 +情 +者 +最 +立 +代 +想 +已 +通 +並 +提 +直 +題 +黨 +程 +展 +五 +果 +料 +象 +員 +革 +位 +入 +常 +文 +總 +次 +品 +式 +活 +設 +及 +管 +特 +件 +長 +求 +老 +頭 +基 +資 +邊 +流 +路 +級 +少 +圖 +山 +統 +接 +知 +較 +將 +組 +見 +計 +別 +她 +手 +角 +期 +根 +論 +運 +農 +指 +幾 +九 +區 +強 +放 +決 +西 +被 +幹 +做 +必 +戰 +先 +回 +則 +任 +取 +據 +處 +隊 +南 +給 +色 +光 +門 +即 +保 +治 +北 +造 +百 +規 +熱 +領 +七 +海 +口 +東 +導 +器 +壓 +志 +世 +金 +增 +爭 +濟 +階 +油 +思 +術 +極 +交 +受 +聯 +什 +認 +六 +共 +權 +收 +證 +改 +清 +美 +再 +採 +轉 +更 +單 +風 +切 +打 +白 +教 +速 +花 +帶 +安 +場 +身 +車 +例 +真 +務 +具 +萬 +每 +目 +至 +達 +走 +積 +示 +議 +聲 +報 +鬥 +完 +類 +八 +離 +華 +名 +確 +才 +科 +張 +信 +馬 +節 +話 +米 +整 +空 +元 +況 +今 +集 +溫 +傳 +土 +許 +步 +群 +廣 +石 +記 +需 +段 +研 +界 +拉 +林 +律 +叫 +且 +究 +觀 +越 +織 +裝 +影 +算 +低 +持 +音 +眾 +書 +布 +复 +容 +兒 +須 +際 +商 +非 +驗 +連 +斷 +深 +難 +近 +礦 +千 +週 +委 +素 +技 +備 +半 +辦 +青 +省 +列 +習 +響 +約 +支 +般 +史 +感 +勞 +便 +團 +往 +酸 +歷 +市 +克 +何 +除 +消 +構 +府 +稱 +太 +準 +精 +值 +號 +率 +族 +維 +劃 +選 +標 +寫 +存 +候 +毛 +親 +快 +效 +斯 +院 +查 +江 +型 +眼 +王 +按 +格 +養 +易 +置 +派 +層 +片 +始 +卻 +專 +狀 +育 +廠 +京 +識 +適 +屬 +圓 +包 +火 +住 +調 +滿 +縣 +局 +照 +參 +紅 +細 +引 +聽 +該 +鐵 +價 +嚴 +首 +底 +液 +官 +德 +隨 +病 +蘇 +失 +爾 +死 +講 +配 +女 +黃 +推 +顯 +談 +罪 +神 +藝 +呢 +席 +含 +企 +望 +密 +批 +營 +項 +防 +舉 +球 +英 +氧 +勢 +告 +李 +台 +落 +木 +幫 +輪 +破 +亞 +師 +圍 +注 +遠 +字 +材 +排 +供 +河 +態 +封 +另 +施 +減 +樹 +溶 +怎 +止 +案 +言 +士 +均 +武 +固 +葉 +魚 +波 +視 +僅 +費 +緊 +愛 +左 +章 +早 +朝 +害 +續 +輕 +服 +試 +食 +充 +兵 +源 +判 +護 +司 +足 +某 +練 +差 +致 +板 +田 +降 +黑 +犯 +負 +擊 +范 +繼 +興 +似 +餘 +堅 +曲 +輸 +修 +故 +城 +夫 +夠 +送 +筆 +船 +佔 +右 +財 +吃 +富 +春 +職 +覺 +漢 +畫 +功 +巴 +跟 +雖 +雜 +飛 +檢 +吸 +助 +昇 +陽 +互 +初 +創 +抗 +考 +投 +壞 +策 +古 +徑 +換 +未 +跑 +留 +鋼 +曾 +端 +責 +站 +簡 +述 +錢 +副 +盡 +帝 +射 +草 +衝 +承 +獨 +令 +限 +阿 +宣 +環 +雙 +請 +超 +微 +讓 +控 +州 +良 +軸 +找 +否 +紀 +益 +依 +優 +頂 +礎 +載 +倒 +房 +突 +坐 +粉 +敵 +略 +客 +袁 +冷 +勝 +絕 +析 +塊 +劑 +測 +絲 +協 +訴 +念 +陳 +仍 +羅 +鹽 +友 +洋 +錯 +苦 +夜 +刑 +移 +頻 +逐 +靠 +混 +母 +短 +皮 +終 +聚 +汽 +村 +雲 +哪 +既 +距 +衛 +停 +烈 +央 +察 +燒 +迅 +境 +若 +印 +洲 +刻 +括 +激 +孔 +搞 +甚 +室 +待 +核 +校 +散 +侵 +吧 +甲 +遊 +久 +菜 +味 +舊 +模 +湖 +貨 +損 +預 +阻 +毫 +普 +穩 +乙 +媽 +植 +息 +擴 +銀 +語 +揮 +酒 +守 +拿 +序 +紙 +醫 +缺 +雨 +嗎 +針 +劉 +啊 +急 +唱 +誤 +訓 +願 +審 +附 +獲 +茶 +鮮 +糧 +斤 +孩 +脫 +硫 +肥 +善 +龍 +演 +父 +漸 +血 +歡 +械 +掌 +歌 +沙 +剛 +攻 +謂 +盾 +討 +晚 +粒 +亂 +燃 +矛 +乎 +殺 +藥 +寧 +魯 +貴 +鐘 +煤 +讀 +班 +伯 +香 +介 +迫 +句 +豐 +培 +握 +蘭 +擔 +弦 +蛋 +沉 +假 +穿 +執 +答 +樂 +誰 +順 +煙 +縮 +徵 +臉 +喜 +松 +腳 +困 +異 +免 +背 +星 +福 +買 +染 +井 +概 +慢 +怕 +磁 +倍 +祖 +皇 +促 +靜 +補 +評 +翻 +肉 +踐 +尼 +衣 +寬 +揚 +棉 +希 +傷 +操 +垂 +秋 +宜 +氫 +套 +督 +振 +架 +亮 +末 +憲 +慶 +編 +牛 +觸 +映 +雷 +銷 +詩 +座 +居 +抓 +裂 +胞 +呼 +娘 +景 +威 +綠 +晶 +厚 +盟 +衡 +雞 +孫 +延 +危 +膠 +屋 +鄉 +臨 +陸 +顧 +掉 +呀 +燈 +歲 +措 +束 +耐 +劇 +玉 +趙 +跳 +哥 +季 +課 +凱 +胡 +額 +款 +紹 +卷 +齊 +偉 +蒸 +殖 +永 +宗 +苗 +川 +爐 +岩 +弱 +零 +楊 +奏 +沿 +露 +桿 +探 +滑 +鎮 +飯 +濃 +航 +懷 +趕 +庫 +奪 +伊 +靈 +稅 +途 +滅 +賽 +歸 +召 +鼓 +播 +盤 +裁 +險 +康 +唯 +錄 +菌 +純 +借 +糖 +蓋 +橫 +符 +私 +努 +堂 +域 +槍 +潤 +幅 +哈 +竟 +熟 +蟲 +澤 +腦 +壤 +碳 +歐 +遍 +側 +寨 +敢 +徹 +慮 +斜 +薄 +庭 +納 +彈 +飼 +伸 +折 +麥 +濕 +暗 +荷 +瓦 +塞 +床 +築 +惡 +戶 +訪 +塔 +奇 +透 +梁 +刀 +旋 +跡 +卡 +氯 +遇 +份 +毒 +泥 +退 +洗 +擺 +灰 +彩 +賣 +耗 +夏 +擇 +忙 +銅 +獻 +硬 +予 +繁 +圈 +雪 +函 +亦 +抽 +篇 +陣 +陰 +丁 +尺 +追 +堆 +雄 +迎 +泛 +爸 +樓 +避 +謀 +噸 +野 +豬 +旗 +累 +偏 +典 +館 +索 +秦 +脂 +潮 +爺 +豆 +忽 +托 +驚 +塑 +遺 +愈 +朱 +替 +纖 +粗 +傾 +尚 +痛 +楚 +謝 +奮 +購 +磨 +君 +池 +旁 +碎 +骨 +監 +捕 +弟 +暴 +割 +貫 +殊 +釋 +詞 +亡 +壁 +頓 +寶 +午 +塵 +聞 +揭 +炮 +殘 +冬 +橋 +婦 +警 +綜 +招 +吳 +付 +浮 +遭 +徐 +您 +搖 +谷 +贊 +箱 +隔 +訂 +男 +吹 +園 +紛 +唐 +敗 +宋 +玻 +巨 +耕 +坦 +榮 +閉 +灣 +鍵 +凡 +駐 +鍋 +救 +恩 +剝 +凝 +鹼 +齒 +截 +煉 +麻 +紡 +禁 +廢 +盛 +版 +緩 +淨 +睛 +昌 +婚 +涉 +筒 +嘴 +插 +岸 +朗 +莊 +街 +藏 +姑 +貿 +腐 +奴 +啦 +慣 +乘 +夥 +恢 +勻 +紗 +扎 +辯 +耳 +彪 +臣 +億 +璃 +抵 +脈 +秀 +薩 +俄 +網 +舞 +店 +噴 +縱 +寸 +汗 +掛 +洪 +賀 +閃 +柬 +爆 +烯 +津 +稻 +牆 +軟 +勇 +像 +滾 +厘 +蒙 +芳 +肯 +坡 +柱 +盪 +腿 +儀 +旅 +尾 +軋 +冰 +貢 +登 +黎 +削 +鑽 +勒 +逃 +障 +氨 +郭 +峰 +幣 +港 +伏 +軌 +畝 +畢 +擦 +莫 +刺 +浪 +秘 +援 +株 +健 +售 +股 +島 +甘 +泡 +睡 +童 +鑄 +湯 +閥 +休 +匯 +舍 +牧 +繞 +炸 +哲 +磷 +績 +朋 +淡 +尖 +啟 +陷 +柴 +呈 +徒 +顏 +淚 +稍 +忘 +泵 +藍 +拖 +洞 +授 +鏡 +辛 +壯 +鋒 +貧 +虛 +彎 +摩 +泰 +幼 +廷 +尊 +窗 +綱 +弄 +隸 +疑 +氏 +宮 +姐 +震 +瑞 +怪 +尤 +琴 +循 +描 +膜 +違 +夾 +腰 +緣 +珠 +窮 +森 +枝 +竹 +溝 +催 +繩 +憶 +邦 +剩 +幸 +漿 +欄 +擁 +牙 +貯 +禮 +濾 +鈉 +紋 +罷 +拍 +咱 +喊 +袖 +埃 +勤 +罰 +焦 +潛 +伍 +墨 +欲 +縫 +姓 +刊 +飽 +仿 +獎 +鋁 +鬼 +麗 +跨 +默 +挖 +鏈 +掃 +喝 +袋 +炭 +污 +幕 +諸 +弧 +勵 +梅 +奶 +潔 +災 +舟 +鑑 +苯 +訟 +抱 +毀 +懂 +寒 +智 +埔 +寄 +屆 +躍 +渡 +挑 +丹 +艱 +貝 +碰 +拔 +爹 +戴 +碼 +夢 +芽 +熔 +赤 +漁 +哭 +敬 +顆 +奔 +鉛 +仲 +虎 +稀 +妹 +乏 +珍 +申 +桌 +遵 +允 +隆 +螺 +倉 +魏 +銳 +曉 +氮 +兼 +隱 +礙 +赫 +撥 +忠 +肅 +缸 +牽 +搶 +博 +巧 +殼 +兄 +杜 +訊 +誠 +碧 +祥 +柯 +頁 +巡 +矩 +悲 +灌 +齡 +倫 +票 +尋 +桂 +鋪 +聖 +恐 +恰 +鄭 +趣 +抬 +荒 +騰 +貼 +柔 +滴 +猛 +闊 +輛 +妻 +填 +撤 +儲 +簽 +鬧 +擾 +紫 +砂 +遞 +戲 +吊 +陶 +伐 +餵 +療 +瓶 +婆 +撫 +臂 +摸 +忍 +蝦 +蠟 +鄰 +胸 +鞏 +擠 +偶 +棄 +槽 +勁 +乳 +鄧 +吉 +仁 +爛 +磚 +租 +烏 +艦 +伴 +瓜 +淺 +丙 +暫 +燥 +橡 +柳 +迷 +暖 +牌 +秧 +膽 +詳 +簧 +踏 +瓷 +譜 +呆 +賓 +糊 +洛 +輝 +憤 +競 +隙 +怒 +粘 +乃 +緒 +肩 +籍 +敏 +塗 +熙 +皆 +偵 +懸 +掘 +享 +糾 +醒 +狂 +鎖 +淀 +恨 +牲 +霸 +爬 +賞 +逆 +玩 +陵 +祝 +秒 +浙 +貌 +役 +彼 +悉 +鴨 +趨 +鳳 +晨 +畜 +輩 +秩 +卵 +署 +梯 +炎 +灘 +棋 +驅 +篩 +峽 +冒 +啥 +壽 +譯 +浸 +泉 +帽 +遲 +矽 +疆 +貸 +漏 +稿 +冠 +嫩 +脅 +芯 +牢 +叛 +蝕 +奧 +鳴 +嶺 +羊 +憑 +串 +塘 +繪 +酵 +融 +盆 +錫 +廟 +籌 +凍 +輔 +攝 +襲 +筋 +拒 +僚 +旱 +鉀 +鳥 +漆 +沈 +眉 +疏 +添 +棒 +穗 +硝 +韓 +逼 +扭 +僑 +涼 +挺 +碗 +栽 +炒 +杯 +患 +餾 +勸 +豪 +遼 +勃 +鴻 +旦 +吏 +拜 +狗 +埋 +輥 +掩 +飲 +搬 +罵 +辭 +勾 +扣 +估 +蔣 +絨 +霧 +丈 +朵 +姆 +擬 +宇 +輯 +陝 +雕 +償 +蓄 +崇 +剪 +倡 +廳 +咬 +駛 +薯 +刷 +斥 +番 +賦 +奉 +佛 +澆 +漫 +曼 +扇 +鈣 +桃 +扶 +仔 +返 +俗 +虧 +腔 +鞋 +棱 +覆 +框 +悄 +叔 +撞 +騙 +勘 +旺 +沸 +孤 +吐 +孟 +渠 +屈 +疾 +妙 +惜 +仰 +狠 +脹 +諧 +拋 +黴 +桑 +崗 +嘛 +衰 +盜 +滲 +臟 +賴 +湧 +甜 +曹 +閱 +肌 +哩 +厲 +烴 +緯 +毅 +昨 +偽 +症 +煮 +嘆 +釘 +搭 +莖 +籠 +酷 +偷 +弓 +錐 +恆 +傑 +坑 +鼻 +翼 +綸 +敘 +獄 +逮 +罐 +絡 +棚 +抑 +膨 +蔬 +寺 +驟 +穆 +冶 +枯 +冊 +屍 +凸 +紳 +坯 +犧 +焰 +轟 +欣 +晉 +瘦 +禦 +錠 +錦 +喪 +旬 +鍛 +壟 +搜 +撲 +邀 +亭 +酯 +邁 +舒 +脆 +酶 +閒 +憂 +酚 +頑 +羽 +漲 +卸 +仗 +陪 +闢 +懲 +杭 +姚 +肚 +捉 +飄 +漂 +昆 +欺 +吾 +郎 +烷 +汁 +呵 +飾 +蕭 +雅 +郵 +遷 +燕 +撒 +姻 +赴 +宴 +煩 +債 +帳 +斑 +鈴 +旨 +醇 +董 +餅 +雛 +姿 +拌 +傅 +腹 +妥 +揉 +賢 +拆 +歪 +葡 +胺 +丟 +浩 +徽 +昂 +墊 +擋 +覽 +貪 +慰 +繳 +汪 +慌 +馮 +諾 +姜 +誼 +兇 +劣 +誣 +耀 +昏 +躺 +盈 +騎 +喬 +溪 +叢 +盧 +抹 +悶 +諮 +刮 +駕 +纜 +悟 +摘 +鉺 +擲 +頗 +幻 +柄 +惠 +慘 +佳 +仇 +臘 +窩 +滌 +劍 +瞧 +堡 +潑 +蔥 +罩 +霍 +撈 +胎 +蒼 +濱 +倆 +捅 +湘 +砍 +霞 +邵 +萄 +瘋 +淮 +遂 +熊 +糞 +烘 +宿 +檔 +戈 +駁 +嫂 +裕 +徙 +箭 +捐 +腸 +撐 +曬 +辨 +殿 +蓮 +攤 +攪 +醬 +屏 +疫 +哀 +蔡 +堵 +沫 +皺 +暢 +疊 +閣 +萊 +敲 +轄 +鉤 +痕 +壩 +巷 +餓 +禍 +丘 +玄 +溜 +曰 +邏 +彭 +嘗 +卿 +妨 +艇 +吞 +韋 +怨 +矮 +歇 +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/english.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/english.go new file mode 100644 index 000000000..f69e8a473 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/english.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt + // $ crc32 english.txt + // c1dbd296 + checksum := crc32.ChecksumIEEE([]byte(english)) + if fmt.Sprintf("%x", checksum) != "c1dbd296" { + panic("english checksum invalid") + } +} + +// English is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt +var English = strings.Split(strings.TrimSpace(english), "\n") +var english = `abandon +ability +able +about +above +absent +absorb +abstract +absurd +abuse +access +accident +account +accuse +achieve +acid +acoustic +acquire +across +act +action +actor +actress +actual +adapt +add +addict +address +adjust +admit +adult +advance +advice +aerobic +affair +afford +afraid +again +age +agent +agree +ahead +aim +air +airport +aisle +alarm +album +alcohol +alert +alien +all +alley +allow +almost +alone +alpha +already +also +alter +always +amateur +amazing +among +amount +amused +analyst +anchor +ancient +anger +angle +angry +animal +ankle +announce +annual +another +answer +antenna +antique +anxiety +any +apart +apology +appear +apple +approve +april +arch +arctic +area +arena +argue +arm +armed +armor +army +around +arrange +arrest +arrive +arrow +art +artefact +artist +artwork +ask +aspect +assault +asset +assist +assume +asthma +athlete +atom +attack +attend +attitude +attract +auction +audit +august +aunt +author +auto +autumn +average +avocado +avoid +awake +aware +away +awesome +awful +awkward +axis +baby +bachelor +bacon +badge +bag +balance +balcony +ball +bamboo +banana +banner +bar +barely +bargain +barrel +base +basic +basket +battle +beach +bean +beauty +because +become +beef +before +begin +behave +behind +believe +below +belt +bench +benefit +best +betray +better +between +beyond +bicycle +bid +bike +bind +biology +bird +birth +bitter +black +blade +blame +blanket +blast +bleak +bless +blind +blood +blossom +blouse +blue +blur +blush +board +boat +body +boil +bomb +bone +bonus +book +boost +border +boring +borrow +boss +bottom +bounce +box +boy +bracket +brain +brand +brass +brave +bread +breeze +brick +bridge +brief +bright +bring +brisk +broccoli +broken +bronze +broom +brother +brown +brush +bubble +buddy +budget +buffalo +build +bulb +bulk +bullet +bundle +bunker +burden +burger +burst +bus +business +busy +butter +buyer +buzz +cabbage +cabin +cable +cactus +cage +cake +call +calm +camera +camp +can +canal +cancel +candy +cannon +canoe +canvas +canyon +capable +capital +captain +car +carbon +card +cargo +carpet +carry +cart +case +cash +casino +castle +casual +cat +catalog +catch +category +cattle +caught +cause +caution +cave +ceiling +celery +cement +census +century +cereal +certain +chair +chalk +champion +change +chaos +chapter +charge +chase +chat +cheap +check +cheese +chef +cherry +chest +chicken +chief +child +chimney +choice +choose +chronic +chuckle +chunk +churn +cigar +cinnamon +circle +citizen +city +civil +claim +clap +clarify +claw +clay +clean +clerk +clever +click +client +cliff +climb +clinic +clip +clock +clog +close +cloth +cloud +clown +club +clump +cluster +clutch +coach +coast +coconut +code +coffee +coil +coin +collect +color +column +combine +come +comfort +comic +common +company +concert +conduct +confirm +congress +connect +consider +control +convince +cook +cool +copper +copy +coral +core +corn +correct +cost +cotton +couch +country +couple +course +cousin +cover +coyote +crack +cradle +craft +cram +crane +crash +crater +crawl +crazy +cream +credit +creek +crew +cricket +crime +crisp +critic +crop +cross +crouch +crowd +crucial +cruel +cruise +crumble +crunch +crush +cry +crystal +cube +culture +cup +cupboard +curious +current +curtain +curve +cushion +custom +cute +cycle +dad +damage +damp +dance +danger +daring +dash +daughter +dawn +day +deal +debate +debris +decade +december +decide +decline +decorate +decrease +deer +defense +define +defy +degree +delay +deliver +demand +demise +denial +dentist +deny +depart +depend +deposit +depth +deputy +derive +describe +desert +design +desk +despair +destroy +detail +detect +develop +device +devote +diagram +dial +diamond +diary +dice +diesel +diet +differ +digital +dignity +dilemma +dinner +dinosaur +direct +dirt +disagree +discover +disease +dish +dismiss +disorder +display +distance +divert +divide +divorce +dizzy +doctor +document +dog +doll +dolphin +domain +donate +donkey +donor +door +dose +double +dove +draft +dragon +drama +drastic +draw +dream +dress +drift +drill +drink +drip +drive +drop +drum +dry +duck +dumb +dune +during +dust +dutch +duty +dwarf +dynamic +eager +eagle +early +earn +earth +easily +east +easy +echo +ecology +economy +edge +edit +educate +effort +egg +eight +either +elbow +elder +electric +elegant +element +elephant +elevator +elite +else +embark +embody +embrace +emerge +emotion +employ +empower +empty +enable +enact +end +endless +endorse +enemy +energy +enforce +engage +engine +enhance +enjoy +enlist +enough +enrich +enroll +ensure +enter +entire +entry +envelope +episode +equal +equip +era +erase +erode +erosion +error +erupt +escape +essay +essence +estate +eternal +ethics +evidence +evil +evoke +evolve +exact +example +excess +exchange +excite +exclude +excuse +execute +exercise +exhaust +exhibit +exile +exist +exit +exotic +expand +expect +expire +explain +expose +express +extend +extra +eye +eyebrow +fabric +face +faculty +fade +faint +faith +fall +false +fame +family +famous +fan +fancy +fantasy +farm +fashion +fat +fatal +father +fatigue +fault +favorite +feature +february +federal +fee +feed +feel +female +fence +festival +fetch +fever +few +fiber +fiction +field +figure +file +film +filter +final +find +fine +finger +finish +fire +firm +first +fiscal +fish +fit +fitness +fix +flag +flame +flash +flat +flavor +flee +flight +flip +float +flock +floor +flower +fluid +flush +fly +foam +focus +fog +foil +fold +follow +food +foot +force +forest +forget +fork +fortune +forum +forward +fossil +foster +found +fox +fragile +frame +frequent +fresh +friend +fringe +frog +front +frost +frown +frozen +fruit +fuel +fun +funny +furnace +fury +future +gadget +gain +galaxy +gallery +game +gap +garage +garbage +garden +garlic +garment +gas +gasp +gate +gather +gauge +gaze +general +genius +genre +gentle +genuine +gesture +ghost +giant +gift +giggle +ginger +giraffe +girl +give +glad +glance +glare +glass +glide +glimpse +globe +gloom +glory +glove +glow +glue +goat +goddess +gold +good +goose +gorilla +gospel +gossip +govern +gown +grab +grace +grain +grant +grape +grass +gravity +great +green +grid +grief +grit +grocery +group +grow +grunt +guard +guess +guide +guilt +guitar +gun +gym +habit +hair +half +hammer +hamster +hand +happy +harbor +hard +harsh +harvest +hat +have +hawk +hazard +head +health +heart +heavy +hedgehog +height +hello +helmet +help +hen +hero +hidden +high +hill +hint +hip +hire +history +hobby +hockey +hold +hole +holiday +hollow +home +honey +hood +hope +horn +horror +horse +hospital +host +hotel +hour +hover +hub +huge +human +humble +humor +hundred +hungry +hunt +hurdle +hurry +hurt +husband +hybrid +ice +icon +idea +identify +idle +ignore +ill +illegal +illness +image +imitate +immense +immune +impact +impose +improve +impulse +inch +include +income +increase +index +indicate +indoor +industry +infant +inflict +inform +inhale +inherit +initial +inject +injury +inmate +inner +innocent +input +inquiry +insane +insect +inside +inspire +install +intact +interest +into +invest +invite +involve +iron +island +isolate +issue +item +ivory +jacket +jaguar +jar +jazz +jealous +jeans +jelly +jewel +job +join +joke +journey +joy +judge +juice +jump +jungle +junior +junk +just +kangaroo +keen +keep +ketchup +key +kick +kid +kidney +kind +kingdom +kiss +kit +kitchen +kite +kitten +kiwi +knee +knife +knock +know +lab +label +labor +ladder +lady +lake +lamp +language +laptop +large +later +latin +laugh +laundry +lava +law +lawn +lawsuit +layer +lazy +leader +leaf +learn +leave +lecture +left +leg +legal +legend +leisure +lemon +lend +length +lens +leopard +lesson +letter +level +liar +liberty +library +license +life +lift +light +like +limb +limit +link +lion +liquid +list +little +live +lizard +load +loan +lobster +local +lock +logic +lonely +long +loop +lottery +loud +lounge +love +loyal +lucky +luggage +lumber +lunar +lunch +luxury +lyrics +machine +mad +magic +magnet +maid +mail +main +major +make +mammal +man +manage +mandate +mango +mansion +manual +maple +marble +march +margin +marine +market +marriage +mask +mass +master +match +material +math +matrix +matter +maximum +maze +meadow +mean +measure +meat +mechanic +medal +media +melody +melt +member +memory +mention +menu +mercy +merge +merit +merry +mesh +message +metal +method +middle +midnight +milk +million +mimic +mind +minimum +minor +minute +miracle +mirror +misery +miss +mistake +mix +mixed +mixture +mobile +model +modify +mom +moment +monitor +monkey +monster +month +moon +moral +more +morning +mosquito +mother +motion +motor +mountain +mouse +move +movie +much +muffin +mule +multiply +muscle +museum +mushroom +music +must +mutual +myself +mystery +myth +naive +name +napkin +narrow +nasty +nation +nature +near +neck +need +negative +neglect +neither +nephew +nerve +nest +net +network +neutral +never +news +next +nice +night +noble +noise +nominee +noodle +normal +north +nose +notable +note +nothing +notice +novel +now +nuclear +number +nurse +nut +oak +obey +object +oblige +obscure +observe +obtain +obvious +occur +ocean +october +odor +off +offer +office +often +oil +okay +old +olive +olympic +omit +once +one +onion +online +only +open +opera +opinion +oppose +option +orange +orbit +orchard +order +ordinary +organ +orient +original +orphan +ostrich +other +outdoor +outer +output +outside +oval +oven +over +own +owner +oxygen +oyster +ozone +pact +paddle +page +pair +palace +palm +panda +panel +panic +panther +paper +parade +parent +park +parrot +party +pass +patch +path +patient +patrol +pattern +pause +pave +payment +peace +peanut +pear +peasant +pelican +pen +penalty +pencil +people +pepper +perfect +permit +person +pet +phone +photo +phrase +physical +piano +picnic +picture +piece +pig +pigeon +pill +pilot +pink +pioneer +pipe +pistol +pitch +pizza +place +planet +plastic +plate +play +please +pledge +pluck +plug +plunge +poem +poet +point +polar +pole +police +pond +pony +pool +popular +portion +position +possible +post +potato +pottery +poverty +powder +power +practice +praise +predict +prefer +prepare +present +pretty +prevent +price +pride +primary +print +priority +prison +private +prize +problem +process +produce +profit +program +project +promote +proof +property +prosper +protect +proud +provide +public +pudding +pull +pulp +pulse +pumpkin +punch +pupil +puppy +purchase +purity +purpose +purse +push +put +puzzle +pyramid +quality +quantum +quarter +question +quick +quit +quiz +quote +rabbit +raccoon +race +rack +radar +radio +rail +rain +raise +rally +ramp +ranch +random +range +rapid +rare +rate +rather +raven +raw +razor +ready +real +reason +rebel +rebuild +recall +receive +recipe +record +recycle +reduce +reflect +reform +refuse +region +regret +regular +reject +relax +release +relief +rely +remain +remember +remind +remove +render +renew +rent +reopen +repair +repeat +replace +report +require +rescue +resemble +resist +resource +response +result +retire +retreat +return +reunion +reveal +review +reward +rhythm +rib +ribbon +rice +rich +ride +ridge +rifle +right +rigid +ring +riot +ripple +risk +ritual +rival +river +road +roast +robot +robust +rocket +romance +roof +rookie +room +rose +rotate +rough +round +route +royal +rubber +rude +rug +rule +run +runway +rural +sad +saddle +sadness +safe +sail +salad +salmon +salon +salt +salute +same +sample +sand +satisfy +satoshi +sauce +sausage +save +say +scale +scan +scare +scatter +scene +scheme +school +science +scissors +scorpion +scout +scrap +screen +script +scrub +sea +search +season +seat +second +secret +section +security +seed +seek +segment +select +sell +seminar +senior +sense +sentence +series +service +session +settle +setup +seven +shadow +shaft +shallow +share +shed +shell +sheriff +shield +shift +shine +ship +shiver +shock +shoe +shoot +shop +short +shoulder +shove +shrimp +shrug +shuffle +shy +sibling +sick +side +siege +sight +sign +silent +silk +silly +silver +similar +simple +since +sing +siren +sister +situate +six +size +skate +sketch +ski +skill +skin +skirt +skull +slab +slam +sleep +slender +slice +slide +slight +slim +slogan +slot +slow +slush +small +smart +smile +smoke +smooth +snack +snake +snap +sniff +snow +soap +soccer +social +sock +soda +soft +solar +soldier +solid +solution +solve +someone +song +soon +sorry +sort +soul +sound +soup +source +south +space +spare +spatial +spawn +speak +special +speed +spell +spend +sphere +spice +spider +spike +spin +spirit +split +spoil +sponsor +spoon +sport +spot +spray +spread +spring +spy +square +squeeze +squirrel +stable +stadium +staff +stage +stairs +stamp +stand +start +state +stay +steak +steel +stem +step +stereo +stick +still +sting +stock +stomach +stone +stool +story +stove +strategy +street +strike +strong +struggle +student +stuff +stumble +style +subject +submit +subway +success +such +sudden +suffer +sugar +suggest +suit +summer +sun +sunny +sunset +super +supply +supreme +sure +surface +surge +surprise +surround +survey +suspect +sustain +swallow +swamp +swap +swarm +swear +sweet +swift +swim +swing +switch +sword +symbol +symptom +syrup +system +table +tackle +tag +tail +talent +talk +tank +tape +target +task +taste +tattoo +taxi +teach +team +tell +ten +tenant +tennis +tent +term +test +text +thank +that +theme +then +theory +there +they +thing +this +thought +three +thrive +throw +thumb +thunder +ticket +tide +tiger +tilt +timber +time +tiny +tip +tired +tissue +title +toast +tobacco +today +toddler +toe +together +toilet +token +tomato +tomorrow +tone +tongue +tonight +tool +tooth +top +topic +topple +torch +tornado +tortoise +toss +total +tourist +toward +tower +town +toy +track +trade +traffic +tragic +train +transfer +trap +trash +travel +tray +treat +tree +trend +trial +tribe +trick +trigger +trim +trip +trophy +trouble +truck +true +truly +trumpet +trust +truth +try +tube +tuition +tumble +tuna +tunnel +turkey +turn +turtle +twelve +twenty +twice +twin +twist +two +type +typical +ugly +umbrella +unable +unaware +uncle +uncover +under +undo +unfair +unfold +unhappy +uniform +unique +unit +universe +unknown +unlock +until +unusual +unveil +update +upgrade +uphold +upon +upper +upset +urban +urge +usage +use +used +useful +useless +usual +utility +vacant +vacuum +vague +valid +valley +valve +van +vanish +vapor +various +vast +vault +vehicle +velvet +vendor +venture +venue +verb +verify +version +very +vessel +veteran +viable +vibrant +vicious +victory +video +view +village +vintage +violin +virtual +virus +visa +visit +visual +vital +vivid +vocal +voice +void +volcano +volume +vote +voyage +wage +wagon +wait +walk +wall +walnut +want +warfare +warm +warrior +wash +wasp +waste +water +wave +way +wealth +weapon +wear +weasel +weather +web +wedding +weekend +weird +welcome +west +wet +whale +what +wheat +wheel +when +where +whip +whisper +wide +width +wife +wild +will +win +window +wine +wing +wink +winner +winter +wire +wisdom +wise +wish +witness +wolf +woman +wonder +wood +wool +word +work +world +worry +worth +wrap +wreck +wrestle +wrist +write +wrong +yard +year +yellow +you +young +youth +zebra +zero +zone +zoo +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/french.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/french.go new file mode 100644 index 000000000..1ae685d3a --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/french.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/french.txt + // $ crc32 french.txt + // 3e56b216 + checksum := crc32.ChecksumIEEE([]byte(french)) + if fmt.Sprintf("%x", checksum) != "3e56b216" { + panic("french checksum invalid") + } +} + +// French is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/french.txt +var French = strings.Split(strings.TrimSpace(french), "\n") +var french = `abaisser +abandon +abdiquer +abeille +abolir +aborder +aboutir +aboyer +abrasif +abreuver +abriter +abroger +abrupt +absence +absolu +absurde +abusif +abyssal +académie +acajou +acarien +accabler +accepter +acclamer +accolade +accroche +accuser +acerbe +achat +acheter +aciduler +acier +acompte +acquérir +acronyme +acteur +actif +actuel +adepte +adéquat +adhésif +adjectif +adjuger +admettre +admirer +adopter +adorer +adoucir +adresse +adroit +adulte +adverbe +aérer +aéronef +affaire +affecter +affiche +affreux +affubler +agacer +agencer +agile +agiter +agrafer +agréable +agrume +aider +aiguille +ailier +aimable +aisance +ajouter +ajuster +alarmer +alchimie +alerte +algèbre +algue +aliéner +aliment +alléger +alliage +allouer +allumer +alourdir +alpaga +altesse +alvéole +amateur +ambigu +ambre +aménager +amertume +amidon +amiral +amorcer +amour +amovible +amphibie +ampleur +amusant +analyse +anaphore +anarchie +anatomie +ancien +anéantir +angle +angoisse +anguleux +animal +annexer +annonce +annuel +anodin +anomalie +anonyme +anormal +antenne +antidote +anxieux +apaiser +apéritif +aplanir +apologie +appareil +appeler +apporter +appuyer +aquarium +aqueduc +arbitre +arbuste +ardeur +ardoise +argent +arlequin +armature +armement +armoire +armure +arpenter +arracher +arriver +arroser +arsenic +artériel +article +aspect +asphalte +aspirer +assaut +asservir +assiette +associer +assurer +asticot +astre +astuce +atelier +atome +atrium +atroce +attaque +attentif +attirer +attraper +aubaine +auberge +audace +audible +augurer +aurore +automne +autruche +avaler +avancer +avarice +avenir +averse +aveugle +aviateur +avide +avion +aviser +avoine +avouer +avril +axial +axiome +badge +bafouer +bagage +baguette +baignade +balancer +balcon +baleine +balisage +bambin +bancaire +bandage +banlieue +bannière +banquier +barbier +baril +baron +barque +barrage +bassin +bastion +bataille +bateau +batterie +baudrier +bavarder +belette +bélier +belote +bénéfice +berceau +berger +berline +bermuda +besace +besogne +bétail +beurre +biberon +bicycle +bidule +bijou +bilan +bilingue +billard +binaire +biologie +biopsie +biotype +biscuit +bison +bistouri +bitume +bizarre +blafard +blague +blanchir +blessant +blinder +blond +bloquer +blouson +bobard +bobine +boire +boiser +bolide +bonbon +bondir +bonheur +bonifier +bonus +bordure +borne +botte +boucle +boueux +bougie +boulon +bouquin +bourse +boussole +boutique +boxeur +branche +brasier +brave +brebis +brèche +breuvage +bricoler +brigade +brillant +brioche +brique +brochure +broder +bronzer +brousse +broyeur +brume +brusque +brutal +bruyant +buffle +buisson +bulletin +bureau +burin +bustier +butiner +butoir +buvable +buvette +cabanon +cabine +cachette +cadeau +cadre +caféine +caillou +caisson +calculer +calepin +calibre +calmer +calomnie +calvaire +camarade +caméra +camion +campagne +canal +caneton +canon +cantine +canular +capable +caporal +caprice +capsule +capter +capuche +carabine +carbone +caresser +caribou +carnage +carotte +carreau +carton +cascade +casier +casque +cassure +causer +caution +cavalier +caverne +caviar +cédille +ceinture +céleste +cellule +cendrier +censurer +central +cercle +cérébral +cerise +cerner +cerveau +cesser +chagrin +chaise +chaleur +chambre +chance +chapitre +charbon +chasseur +chaton +chausson +chavirer +chemise +chenille +chéquier +chercher +cheval +chien +chiffre +chignon +chimère +chiot +chlorure +chocolat +choisir +chose +chouette +chrome +chute +cigare +cigogne +cimenter +cinéma +cintrer +circuler +cirer +cirque +citerne +citoyen +citron +civil +clairon +clameur +claquer +classe +clavier +client +cligner +climat +clivage +cloche +clonage +cloporte +cobalt +cobra +cocasse +cocotier +coder +codifier +coffre +cogner +cohésion +coiffer +coincer +colère +colibri +colline +colmater +colonel +combat +comédie +commande +compact +concert +conduire +confier +congeler +connoter +consonne +contact +convexe +copain +copie +corail +corbeau +cordage +corniche +corpus +correct +cortège +cosmique +costume +coton +coude +coupure +courage +couteau +couvrir +coyote +crabe +crainte +cravate +crayon +créature +créditer +crémeux +creuser +crevette +cribler +crier +cristal +critère +croire +croquer +crotale +crucial +cruel +crypter +cubique +cueillir +cuillère +cuisine +cuivre +culminer +cultiver +cumuler +cupide +curatif +curseur +cyanure +cycle +cylindre +cynique +daigner +damier +danger +danseur +dauphin +débattre +débiter +déborder +débrider +débutant +décaler +décembre +déchirer +décider +déclarer +décorer +décrire +décupler +dédale +déductif +déesse +défensif +défiler +défrayer +dégager +dégivrer +déglutir +dégrafer +déjeuner +délice +déloger +demander +demeurer +démolir +dénicher +dénouer +dentelle +dénuder +départ +dépenser +déphaser +déplacer +déposer +déranger +dérober +désastre +descente +désert +désigner +désobéir +dessiner +destrier +détacher +détester +détourer +détresse +devancer +devenir +deviner +devoir +diable +dialogue +diamant +dicter +différer +digérer +digital +digne +diluer +dimanche +diminuer +dioxyde +directif +diriger +discuter +disposer +dissiper +distance +divertir +diviser +docile +docteur +dogme +doigt +domaine +domicile +dompter +donateur +donjon +donner +dopamine +dortoir +dorure +dosage +doseur +dossier +dotation +douanier +double +douceur +douter +doyen +dragon +draper +dresser +dribbler +droiture +duperie +duplexe +durable +durcir +dynastie +éblouir +écarter +écharpe +échelle +éclairer +éclipse +éclore +écluse +école +économie +écorce +écouter +écraser +écrémer +écrivain +écrou +écume +écureuil +édifier +éduquer +effacer +effectif +effigie +effort +effrayer +effusion +égaliser +égarer +éjecter +élaborer +élargir +électron +élégant +éléphant +élève +éligible +élitisme +éloge +élucider +éluder +emballer +embellir +embryon +émeraude +émission +emmener +émotion +émouvoir +empereur +employer +emporter +emprise +émulsion +encadrer +enchère +enclave +encoche +endiguer +endosser +endroit +enduire +énergie +enfance +enfermer +enfouir +engager +engin +englober +énigme +enjamber +enjeu +enlever +ennemi +ennuyeux +enrichir +enrobage +enseigne +entasser +entendre +entier +entourer +entraver +énumérer +envahir +enviable +envoyer +enzyme +éolien +épaissir +épargne +épatant +épaule +épicerie +épidémie +épier +épilogue +épine +épisode +épitaphe +époque +épreuve +éprouver +épuisant +équerre +équipe +ériger +érosion +erreur +éruption +escalier +espadon +espèce +espiègle +espoir +esprit +esquiver +essayer +essence +essieu +essorer +estime +estomac +estrade +étagère +étaler +étanche +étatique +éteindre +étendoir +éternel +éthanol +éthique +ethnie +étirer +étoffer +étoile +étonnant +étourdir +étrange +étroit +étude +euphorie +évaluer +évasion +éventail +évidence +éviter +évolutif +évoquer +exact +exagérer +exaucer +exceller +excitant +exclusif +excuse +exécuter +exemple +exercer +exhaler +exhorter +exigence +exiler +exister +exotique +expédier +explorer +exposer +exprimer +exquis +extensif +extraire +exulter +fable +fabuleux +facette +facile +facture +faiblir +falaise +fameux +famille +farceur +farfelu +farine +farouche +fasciner +fatal +fatigue +faucon +fautif +faveur +favori +fébrile +féconder +fédérer +félin +femme +fémur +fendoir +féodal +fermer +féroce +ferveur +festival +feuille +feutre +février +fiasco +ficeler +fictif +fidèle +figure +filature +filetage +filière +filleul +filmer +filou +filtrer +financer +finir +fiole +firme +fissure +fixer +flairer +flamme +flasque +flatteur +fléau +flèche +fleur +flexion +flocon +flore +fluctuer +fluide +fluvial +folie +fonderie +fongible +fontaine +forcer +forgeron +formuler +fortune +fossile +foudre +fougère +fouiller +foulure +fourmi +fragile +fraise +franchir +frapper +frayeur +frégate +freiner +frelon +frémir +frénésie +frère +friable +friction +frisson +frivole +froid +fromage +frontal +frotter +fruit +fugitif +fuite +fureur +furieux +furtif +fusion +futur +gagner +galaxie +galerie +gambader +garantir +gardien +garnir +garrigue +gazelle +gazon +géant +gélatine +gélule +gendarme +général +génie +genou +gentil +géologie +géomètre +géranium +germe +gestuel +geyser +gibier +gicler +girafe +givre +glace +glaive +glisser +globe +gloire +glorieux +golfeur +gomme +gonfler +gorge +gorille +goudron +gouffre +goulot +goupille +gourmand +goutte +graduel +graffiti +graine +grand +grappin +gratuit +gravir +grenat +griffure +griller +grimper +grogner +gronder +grotte +groupe +gruger +grutier +gruyère +guépard +guerrier +guide +guimauve +guitare +gustatif +gymnaste +gyrostat +habitude +hachoir +halte +hameau +hangar +hanneton +haricot +harmonie +harpon +hasard +hélium +hématome +herbe +hérisson +hermine +héron +hésiter +heureux +hiberner +hibou +hilarant +histoire +hiver +homard +hommage +homogène +honneur +honorer +honteux +horde +horizon +horloge +hormone +horrible +houleux +housse +hublot +huileux +humain +humble +humide +humour +hurler +hydromel +hygiène +hymne +hypnose +idylle +ignorer +iguane +illicite +illusion +image +imbiber +imiter +immense +immobile +immuable +impact +impérial +implorer +imposer +imprimer +imputer +incarner +incendie +incident +incliner +incolore +indexer +indice +inductif +inédit +ineptie +inexact +infini +infliger +informer +infusion +ingérer +inhaler +inhiber +injecter +injure +innocent +inoculer +inonder +inscrire +insecte +insigne +insolite +inspirer +instinct +insulter +intact +intense +intime +intrigue +intuitif +inutile +invasion +inventer +inviter +invoquer +ironique +irradier +irréel +irriter +isoler +ivoire +ivresse +jaguar +jaillir +jambe +janvier +jardin +jauger +jaune +javelot +jetable +jeton +jeudi +jeunesse +joindre +joncher +jongler +joueur +jouissif +journal +jovial +joyau +joyeux +jubiler +jugement +junior +jupon +juriste +justice +juteux +juvénile +kayak +kimono +kiosque +label +labial +labourer +lacérer +lactose +lagune +laine +laisser +laitier +lambeau +lamelle +lampe +lanceur +langage +lanterne +lapin +largeur +larme +laurier +lavabo +lavoir +lecture +légal +léger +légume +lessive +lettre +levier +lexique +lézard +liasse +libérer +libre +licence +licorne +liège +lièvre +ligature +ligoter +ligue +limer +limite +limonade +limpide +linéaire +lingot +lionceau +liquide +lisière +lister +lithium +litige +littoral +livreur +logique +lointain +loisir +lombric +loterie +louer +lourd +loutre +louve +loyal +lubie +lucide +lucratif +lueur +lugubre +luisant +lumière +lunaire +lundi +luron +lutter +luxueux +machine +magasin +magenta +magique +maigre +maillon +maintien +mairie +maison +majorer +malaxer +maléfice +malheur +malice +mallette +mammouth +mandater +maniable +manquant +manteau +manuel +marathon +marbre +marchand +mardi +maritime +marqueur +marron +marteler +mascotte +massif +matériel +matière +matraque +maudire +maussade +mauve +maximal +méchant +méconnu +médaille +médecin +méditer +méduse +meilleur +mélange +mélodie +membre +mémoire +menacer +mener +menhir +mensonge +mentor +mercredi +mérite +merle +messager +mesure +métal +météore +méthode +métier +meuble +miauler +microbe +miette +mignon +migrer +milieu +million +mimique +mince +minéral +minimal +minorer +minute +miracle +miroiter +missile +mixte +mobile +moderne +moelleux +mondial +moniteur +monnaie +monotone +monstre +montagne +monument +moqueur +morceau +morsure +mortier +moteur +motif +mouche +moufle +moulin +mousson +mouton +mouvant +multiple +munition +muraille +murène +murmure +muscle +muséum +musicien +mutation +muter +mutuel +myriade +myrtille +mystère +mythique +nageur +nappe +narquois +narrer +natation +nation +nature +naufrage +nautique +navire +nébuleux +nectar +néfaste +négation +négliger +négocier +neige +nerveux +nettoyer +neurone +neutron +neveu +niche +nickel +nitrate +niveau +noble +nocif +nocturne +noirceur +noisette +nomade +nombreux +nommer +normatif +notable +notifier +notoire +nourrir +nouveau +novateur +novembre +novice +nuage +nuancer +nuire +nuisible +numéro +nuptial +nuque +nutritif +obéir +objectif +obliger +obscur +observer +obstacle +obtenir +obturer +occasion +occuper +océan +octobre +octroyer +octupler +oculaire +odeur +odorant +offenser +officier +offrir +ogive +oiseau +oisillon +olfactif +olivier +ombrage +omettre +onctueux +onduler +onéreux +onirique +opale +opaque +opérer +opinion +opportun +opprimer +opter +optique +orageux +orange +orbite +ordonner +oreille +organe +orgueil +orifice +ornement +orque +ortie +osciller +osmose +ossature +otarie +ouragan +ourson +outil +outrager +ouvrage +ovation +oxyde +oxygène +ozone +paisible +palace +palmarès +palourde +palper +panache +panda +pangolin +paniquer +panneau +panorama +pantalon +papaye +papier +papoter +papyrus +paradoxe +parcelle +paresse +parfumer +parler +parole +parrain +parsemer +partager +parure +parvenir +passion +pastèque +paternel +patience +patron +pavillon +pavoiser +payer +paysage +peigne +peintre +pelage +pélican +pelle +pelouse +peluche +pendule +pénétrer +pénible +pensif +pénurie +pépite +péplum +perdrix +perforer +période +permuter +perplexe +persil +perte +peser +pétale +petit +pétrir +peuple +pharaon +phobie +phoque +photon +phrase +physique +piano +pictural +pièce +pierre +pieuvre +pilote +pinceau +pipette +piquer +pirogue +piscine +piston +pivoter +pixel +pizza +placard +plafond +plaisir +planer +plaque +plastron +plateau +pleurer +plexus +pliage +plomb +plonger +pluie +plumage +pochette +poésie +poète +pointe +poirier +poisson +poivre +polaire +policier +pollen +polygone +pommade +pompier +ponctuel +pondérer +poney +portique +position +posséder +posture +potager +poteau +potion +pouce +poulain +poumon +pourpre +poussin +pouvoir +prairie +pratique +précieux +prédire +préfixe +prélude +prénom +présence +prétexte +prévoir +primitif +prince +prison +priver +problème +procéder +prodige +profond +progrès +proie +projeter +prologue +promener +propre +prospère +protéger +prouesse +proverbe +prudence +pruneau +psychose +public +puceron +puiser +pulpe +pulsar +punaise +punitif +pupitre +purifier +puzzle +pyramide +quasar +querelle +question +quiétude +quitter +quotient +racine +raconter +radieux +ragondin +raideur +raisin +ralentir +rallonge +ramasser +rapide +rasage +ratisser +ravager +ravin +rayonner +réactif +réagir +réaliser +réanimer +recevoir +réciter +réclamer +récolter +recruter +reculer +recycler +rédiger +redouter +refaire +réflexe +réformer +refrain +refuge +régalien +région +réglage +régulier +réitérer +rejeter +rejouer +relatif +relever +relief +remarque +remède +remise +remonter +remplir +remuer +renard +renfort +renifler +renoncer +rentrer +renvoi +replier +reporter +reprise +reptile +requin +réserve +résineux +résoudre +respect +rester +résultat +rétablir +retenir +réticule +retomber +retracer +réunion +réussir +revanche +revivre +révolte +révulsif +richesse +rideau +rieur +rigide +rigoler +rincer +riposter +risible +risque +rituel +rival +rivière +rocheux +romance +rompre +ronce +rondin +roseau +rosier +rotatif +rotor +rotule +rouge +rouille +rouleau +routine +royaume +ruban +rubis +ruche +ruelle +rugueux +ruiner +ruisseau +ruser +rustique +rythme +sabler +saboter +sabre +sacoche +safari +sagesse +saisir +salade +salive +salon +saluer +samedi +sanction +sanglier +sarcasme +sardine +saturer +saugrenu +saumon +sauter +sauvage +savant +savonner +scalpel +scandale +scélérat +scénario +sceptre +schéma +science +scinder +score +scrutin +sculpter +séance +sécable +sécher +secouer +sécréter +sédatif +séduire +seigneur +séjour +sélectif +semaine +sembler +semence +séminal +sénateur +sensible +sentence +séparer +séquence +serein +sergent +sérieux +serrure +sérum +service +sésame +sévir +sevrage +sextuple +sidéral +siècle +siéger +siffler +sigle +signal +silence +silicium +simple +sincère +sinistre +siphon +sirop +sismique +situer +skier +social +socle +sodium +soigneux +soldat +soleil +solitude +soluble +sombre +sommeil +somnoler +sonde +songeur +sonnette +sonore +sorcier +sortir +sosie +sottise +soucieux +soudure +souffle +soulever +soupape +source +soutirer +souvenir +spacieux +spatial +spécial +sphère +spiral +stable +station +sternum +stimulus +stipuler +strict +studieux +stupeur +styliste +sublime +substrat +subtil +subvenir +succès +sucre +suffixe +suggérer +suiveur +sulfate +superbe +supplier +surface +suricate +surmener +surprise +sursaut +survie +suspect +syllabe +symbole +symétrie +synapse +syntaxe +système +tabac +tablier +tactile +tailler +talent +talisman +talonner +tambour +tamiser +tangible +tapis +taquiner +tarder +tarif +tartine +tasse +tatami +tatouage +taupe +taureau +taxer +témoin +temporel +tenaille +tendre +teneur +tenir +tension +terminer +terne +terrible +tétine +texte +thème +théorie +thérapie +thorax +tibia +tiède +timide +tirelire +tiroir +tissu +titane +titre +tituber +toboggan +tolérant +tomate +tonique +tonneau +toponyme +torche +tordre +tornade +torpille +torrent +torse +tortue +totem +toucher +tournage +tousser +toxine +traction +trafic +tragique +trahir +train +trancher +travail +trèfle +tremper +trésor +treuil +triage +tribunal +tricoter +trilogie +triomphe +tripler +triturer +trivial +trombone +tronc +tropical +troupeau +tuile +tulipe +tumulte +tunnel +turbine +tuteur +tutoyer +tuyau +tympan +typhon +typique +tyran +ubuesque +ultime +ultrason +unanime +unifier +union +unique +unitaire +univers +uranium +urbain +urticant +usage +usine +usuel +usure +utile +utopie +vacarme +vaccin +vagabond +vague +vaillant +vaincre +vaisseau +valable +valise +vallon +valve +vampire +vanille +vapeur +varier +vaseux +vassal +vaste +vecteur +vedette +végétal +véhicule +veinard +véloce +vendredi +vénérer +venger +venimeux +ventouse +verdure +vérin +vernir +verrou +verser +vertu +veston +vétéran +vétuste +vexant +vexer +viaduc +viande +victoire +vidange +vidéo +vignette +vigueur +vilain +village +vinaigre +violon +vipère +virement +virtuose +virus +visage +viseur +vision +visqueux +visuel +vital +vitesse +viticole +vitrine +vivace +vivipare +vocation +voguer +voile +voisin +voiture +volaille +volcan +voltiger +volume +vorace +vortex +voter +vouloir +voyage +voyelle +wagon +xénon +yacht +zèbre +zénith +zeste +zoologie +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/italian.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/italian.go new file mode 100644 index 000000000..32cd2cf6d --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/italian.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/italian.txt + // $ crc32 italian.txt + // 2fc7d07e + checksum := crc32.ChecksumIEEE([]byte(italian)) + if fmt.Sprintf("%x", checksum) != "2fc7d07e" { + panic("italian checksum invalid") + } +} + +// Italian is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/italian.txt +var Italian = strings.Split(strings.TrimSpace(italian), "\n") +var italian = `abaco +abbaglio +abbinato +abete +abisso +abolire +abrasivo +abrogato +accadere +accenno +accusato +acetone +achille +acido +acqua +acre +acrilico +acrobata +acuto +adagio +addebito +addome +adeguato +aderire +adipe +adottare +adulare +affabile +affetto +affisso +affranto +aforisma +afoso +africano +agave +agente +agevole +aggancio +agire +agitare +agonismo +agricolo +agrumeto +aguzzo +alabarda +alato +albatro +alberato +albo +albume +alce +alcolico +alettone +alfa +algebra +aliante +alibi +alimento +allagato +allegro +allievo +allodola +allusivo +almeno +alogeno +alpaca +alpestre +altalena +alterno +alticcio +altrove +alunno +alveolo +alzare +amalgama +amanita +amarena +ambito +ambrato +ameba +america +ametista +amico +ammasso +ammenda +ammirare +ammonito +amore +ampio +ampliare +amuleto +anacardo +anagrafe +analista +anarchia +anatra +anca +ancella +ancora +andare +andrea +anello +angelo +angolare +angusto +anima +annegare +annidato +anno +annuncio +anonimo +anticipo +anzi +apatico +apertura +apode +apparire +appetito +appoggio +approdo +appunto +aprile +arabica +arachide +aragosta +araldica +arancio +aratura +arazzo +arbitro +archivio +ardito +arenile +argento +argine +arguto +aria +armonia +arnese +arredato +arringa +arrosto +arsenico +arso +artefice +arzillo +asciutto +ascolto +asepsi +asettico +asfalto +asino +asola +aspirato +aspro +assaggio +asse +assoluto +assurdo +asta +astenuto +astice +astratto +atavico +ateismo +atomico +atono +attesa +attivare +attorno +attrito +attuale +ausilio +austria +autista +autonomo +autunno +avanzato +avere +avvenire +avviso +avvolgere +azione +azoto +azzimo +azzurro +babele +baccano +bacino +baco +badessa +badilata +bagnato +baita +balcone +baldo +balena +ballata +balzano +bambino +bandire +baraonda +barbaro +barca +baritono +barlume +barocco +basilico +basso +batosta +battuto +baule +bava +bavosa +becco +beffa +belgio +belva +benda +benevole +benigno +benzina +bere +berlina +beta +bibita +bici +bidone +bifido +biga +bilancia +bimbo +binocolo +biologo +bipede +bipolare +birbante +birra +biscotto +bisesto +bisnonno +bisonte +bisturi +bizzarro +blando +blatta +bollito +bonifico +bordo +bosco +botanico +bottino +bozzolo +braccio +bradipo +brama +branca +bravura +bretella +brevetto +brezza +briglia +brillante +brindare +broccolo +brodo +bronzina +brullo +bruno +bubbone +buca +budino +buffone +buio +bulbo +buono +burlone +burrasca +bussola +busta +cadetto +caduco +calamaro +calcolo +calesse +calibro +calmo +caloria +cambusa +camerata +camicia +cammino +camola +campale +canapa +candela +cane +canino +canotto +cantina +capace +capello +capitolo +capogiro +cappero +capra +capsula +carapace +carcassa +cardo +carisma +carovana +carretto +cartolina +casaccio +cascata +caserma +caso +cassone +castello +casuale +catasta +catena +catrame +cauto +cavillo +cedibile +cedrata +cefalo +celebre +cellulare +cena +cenone +centesimo +ceramica +cercare +certo +cerume +cervello +cesoia +cespo +ceto +chela +chiaro +chicca +chiedere +chimera +china +chirurgo +chitarra +ciao +ciclismo +cifrare +cigno +cilindro +ciottolo +circa +cirrosi +citrico +cittadino +ciuffo +civetta +civile +classico +clinica +cloro +cocco +codardo +codice +coerente +cognome +collare +colmato +colore +colposo +coltivato +colza +coma +cometa +commando +comodo +computer +comune +conciso +condurre +conferma +congelare +coniuge +connesso +conoscere +consumo +continuo +convegno +coperto +copione +coppia +copricapo +corazza +cordata +coricato +cornice +corolla +corpo +corredo +corsia +cortese +cosmico +costante +cottura +covato +cratere +cravatta +creato +credere +cremoso +crescita +creta +criceto +crinale +crisi +critico +croce +cronaca +crostata +cruciale +crusca +cucire +cuculo +cugino +cullato +cupola +curatore +cursore +curvo +cuscino +custode +dado +daino +dalmata +damerino +daniela +dannoso +danzare +datato +davanti +davvero +debutto +decennio +deciso +declino +decollo +decreto +dedicato +definito +deforme +degno +delegare +delfino +delirio +delta +demenza +denotato +dentro +deposito +derapata +derivare +deroga +descritto +deserto +desiderio +desumere +detersivo +devoto +diametro +dicembre +diedro +difeso +diffuso +digerire +digitale +diluvio +dinamico +dinnanzi +dipinto +diploma +dipolo +diradare +dire +dirotto +dirupo +disagio +discreto +disfare +disgelo +disposto +distanza +disumano +dito +divano +divelto +dividere +divorato +doblone +docente +doganale +dogma +dolce +domato +domenica +dominare +dondolo +dono +dormire +dote +dottore +dovuto +dozzina +drago +druido +dubbio +dubitare +ducale +duna +duomo +duplice +duraturo +ebano +eccesso +ecco +eclissi +economia +edera +edicola +edile +editoria +educare +egemonia +egli +egoismo +egregio +elaborato +elargire +elegante +elencato +eletto +elevare +elfico +elica +elmo +elsa +eluso +emanato +emblema +emesso +emiro +emotivo +emozione +empirico +emulo +endemico +enduro +energia +enfasi +enoteca +entrare +enzima +epatite +epilogo +episodio +epocale +eppure +equatore +erario +erba +erboso +erede +eremita +erigere +ermetico +eroe +erosivo +errante +esagono +esame +esanime +esaudire +esca +esempio +esercito +esibito +esigente +esistere +esito +esofago +esortato +esoso +espanso +espresso +essenza +esso +esteso +estimare +estonia +estroso +esultare +etilico +etnico +etrusco +etto +euclideo +europa +evaso +evidenza +evitato +evoluto +evviva +fabbrica +faccenda +fachiro +falco +famiglia +fanale +fanfara +fango +fantasma +fare +farfalla +farinoso +farmaco +fascia +fastoso +fasullo +faticare +fato +favoloso +febbre +fecola +fede +fegato +felpa +feltro +femmina +fendere +fenomeno +fermento +ferro +fertile +fessura +festivo +fetta +feudo +fiaba +fiducia +fifa +figurato +filo +finanza +finestra +finire +fiore +fiscale +fisico +fiume +flacone +flamenco +flebo +flemma +florido +fluente +fluoro +fobico +focaccia +focoso +foderato +foglio +folata +folclore +folgore +fondente +fonetico +fonia +fontana +forbito +forchetta +foresta +formica +fornaio +foro +fortezza +forzare +fosfato +fosso +fracasso +frana +frassino +fratello +freccetta +frenata +fresco +frigo +frollino +fronde +frugale +frutta +fucilata +fucsia +fuggente +fulmine +fulvo +fumante +fumetto +fumoso +fune +funzione +fuoco +furbo +furgone +furore +fuso +futile +gabbiano +gaffe +galateo +gallina +galoppo +gambero +gamma +garanzia +garbo +garofano +garzone +gasdotto +gasolio +gastrico +gatto +gaudio +gazebo +gazzella +geco +gelatina +gelso +gemello +gemmato +gene +genitore +gennaio +genotipo +gergo +ghepardo +ghiaccio +ghisa +giallo +gilda +ginepro +giocare +gioiello +giorno +giove +girato +girone +gittata +giudizio +giurato +giusto +globulo +glutine +gnomo +gobba +golf +gomito +gommone +gonfio +gonna +governo +gracile +grado +grafico +grammo +grande +grattare +gravoso +grazia +greca +gregge +grifone +grigio +grinza +grotta +gruppo +guadagno +guaio +guanto +guardare +gufo +guidare +ibernato +icona +identico +idillio +idolo +idra +idrico +idrogeno +igiene +ignaro +ignorato +ilare +illeso +illogico +illudere +imballo +imbevuto +imbocco +imbuto +immane +immerso +immolato +impacco +impeto +impiego +importo +impronta +inalare +inarcare +inattivo +incanto +incendio +inchino +incisivo +incluso +incontro +incrocio +incubo +indagine +india +indole +inedito +infatti +infilare +inflitto +ingaggio +ingegno +inglese +ingordo +ingrosso +innesco +inodore +inoltrare +inondato +insano +insetto +insieme +insonnia +insulina +intasato +intero +intonaco +intuito +inumidire +invalido +invece +invito +iperbole +ipnotico +ipotesi +ippica +iride +irlanda +ironico +irrigato +irrorare +isolato +isotopo +isterico +istituto +istrice +italia +iterare +labbro +labirinto +lacca +lacerato +lacrima +lacuna +laddove +lago +lampo +lancetta +lanterna +lardoso +larga +laringe +lastra +latenza +latino +lattuga +lavagna +lavoro +legale +leggero +lembo +lentezza +lenza +leone +lepre +lesivo +lessato +lesto +letterale +leva +levigato +libero +lido +lievito +lilla +limatura +limitare +limpido +lineare +lingua +liquido +lira +lirica +lisca +lite +litigio +livrea +locanda +lode +logica +lombare +londra +longevo +loquace +lorenzo +loto +lotteria +luce +lucidato +lumaca +luminoso +lungo +lupo +luppolo +lusinga +lusso +lutto +macabro +macchina +macero +macinato +madama +magico +maglia +magnete +magro +maiolica +malafede +malgrado +malinteso +malsano +malto +malumore +mana +mancia +mandorla +mangiare +manifesto +mannaro +manovra +mansarda +mantide +manubrio +mappa +maratona +marcire +maretta +marmo +marsupio +maschera +massaia +mastino +materasso +matricola +mattone +maturo +mazurca +meandro +meccanico +mecenate +medesimo +meditare +mega +melassa +melis +melodia +meninge +meno +mensola +mercurio +merenda +merlo +meschino +mese +messere +mestolo +metallo +metodo +mettere +miagolare +mica +micelio +michele +microbo +midollo +miele +migliore +milano +milite +mimosa +minerale +mini +minore +mirino +mirtillo +miscela +missiva +misto +misurare +mitezza +mitigare +mitra +mittente +mnemonico +modello +modifica +modulo +mogano +mogio +mole +molosso +monastero +monco +mondina +monetario +monile +monotono +monsone +montato +monviso +mora +mordere +morsicato +mostro +motivato +motosega +motto +movenza +movimento +mozzo +mucca +mucosa +muffa +mughetto +mugnaio +mulatto +mulinello +multiplo +mummia +munto +muovere +murale +musa +muscolo +musica +mutevole +muto +nababbo +nafta +nanometro +narciso +narice +narrato +nascere +nastrare +naturale +nautica +naviglio +nebulosa +necrosi +negativo +negozio +nemmeno +neofita +neretto +nervo +nessuno +nettuno +neutrale +neve +nevrotico +nicchia +ninfa +nitido +nobile +nocivo +nodo +nome +nomina +nordico +normale +norvegese +nostrano +notare +notizia +notturno +novella +nucleo +nulla +numero +nuovo +nutrire +nuvola +nuziale +oasi +obbedire +obbligo +obelisco +oblio +obolo +obsoleto +occasione +occhio +occidente +occorrere +occultare +ocra +oculato +odierno +odorare +offerta +offrire +offuscato +oggetto +oggi +ognuno +olandese +olfatto +oliato +oliva +ologramma +oltre +omaggio +ombelico +ombra +omega +omissione +ondoso +onere +onice +onnivoro +onorevole +onta +operato +opinione +opposto +oracolo +orafo +ordine +orecchino +orefice +orfano +organico +origine +orizzonte +orma +ormeggio +ornativo +orologio +orrendo +orribile +ortensia +ortica +orzata +orzo +osare +oscurare +osmosi +ospedale +ospite +ossa +ossidare +ostacolo +oste +otite +otre +ottagono +ottimo +ottobre +ovale +ovest +ovino +oviparo +ovocito +ovunque +ovviare +ozio +pacchetto +pace +pacifico +padella +padrone +paese +paga +pagina +palazzina +palesare +pallido +palo +palude +pandoro +pannello +paolo +paonazzo +paprica +parabola +parcella +parere +pargolo +pari +parlato +parola +partire +parvenza +parziale +passivo +pasticca +patacca +patologia +pattume +pavone +peccato +pedalare +pedonale +peggio +peloso +penare +pendice +penisola +pennuto +penombra +pensare +pentola +pepe +pepita +perbene +percorso +perdonato +perforare +pergamena +periodo +permesso +perno +perplesso +persuaso +pertugio +pervaso +pesatore +pesista +peso +pestifero +petalo +pettine +petulante +pezzo +piacere +pianta +piattino +piccino +picozza +piega +pietra +piffero +pigiama +pigolio +pigro +pila +pilifero +pillola +pilota +pimpante +pineta +pinna +pinolo +pioggia +piombo +piramide +piretico +pirite +pirolisi +pitone +pizzico +placebo +planare +plasma +platano +plenario +pochezza +poderoso +podismo +poesia +poggiare +polenta +poligono +pollice +polmonite +polpetta +polso +poltrona +polvere +pomice +pomodoro +ponte +popoloso +porfido +poroso +porpora +porre +portata +posa +positivo +possesso +postulato +potassio +potere +pranzo +prassi +pratica +precluso +predica +prefisso +pregiato +prelievo +premere +prenotare +preparato +presenza +pretesto +prevalso +prima +principe +privato +problema +procura +produrre +profumo +progetto +prolunga +promessa +pronome +proposta +proroga +proteso +prova +prudente +prugna +prurito +psiche +pubblico +pudica +pugilato +pugno +pulce +pulito +pulsante +puntare +pupazzo +pupilla +puro +quadro +qualcosa +quasi +querela +quota +raccolto +raddoppio +radicale +radunato +raffica +ragazzo +ragione +ragno +ramarro +ramingo +ramo +randagio +rantolare +rapato +rapina +rappreso +rasatura +raschiato +rasente +rassegna +rastrello +rata +ravveduto +reale +recepire +recinto +recluta +recondito +recupero +reddito +redimere +regalato +registro +regola +regresso +relazione +remare +remoto +renna +replica +reprimere +reputare +resa +residente +responso +restauro +rete +retina +retorica +rettifica +revocato +riassunto +ribadire +ribelle +ribrezzo +ricarica +ricco +ricevere +riciclato +ricordo +ricreduto +ridicolo +ridurre +rifasare +riflesso +riforma +rifugio +rigare +rigettato +righello +rilassato +rilevato +rimanere +rimbalzo +rimedio +rimorchio +rinascita +rincaro +rinforzo +rinnovo +rinomato +rinsavito +rintocco +rinuncia +rinvenire +riparato +ripetuto +ripieno +riportare +ripresa +ripulire +risata +rischio +riserva +risibile +riso +rispetto +ristoro +risultato +risvolto +ritardo +ritegno +ritmico +ritrovo +riunione +riva +riverso +rivincita +rivolto +rizoma +roba +robotico +robusto +roccia +roco +rodaggio +rodere +roditore +rogito +rollio +romantico +rompere +ronzio +rosolare +rospo +rotante +rotondo +rotula +rovescio +rubizzo +rubrica +ruga +rullino +rumine +rumoroso +ruolo +rupe +russare +rustico +sabato +sabbiare +sabotato +sagoma +salasso +saldatura +salgemma +salivare +salmone +salone +saltare +saluto +salvo +sapere +sapido +saporito +saraceno +sarcasmo +sarto +sassoso +satellite +satira +satollo +saturno +savana +savio +saziato +sbadiglio +sbalzo +sbancato +sbarra +sbattere +sbavare +sbendare +sbirciare +sbloccato +sbocciato +sbrinare +sbruffone +sbuffare +scabroso +scadenza +scala +scambiare +scandalo +scapola +scarso +scatenare +scavato +scelto +scenico +scettro +scheda +schiena +sciarpa +scienza +scindere +scippo +sciroppo +scivolo +sclerare +scodella +scolpito +scomparto +sconforto +scoprire +scorta +scossone +scozzese +scriba +scrollare +scrutinio +scuderia +scultore +scuola +scuro +scusare +sdebitare +sdoganare +seccatura +secondo +sedano +seggiola +segnalato +segregato +seguito +selciato +selettivo +sella +selvaggio +semaforo +sembrare +seme +seminato +sempre +senso +sentire +sepolto +sequenza +serata +serbato +sereno +serio +serpente +serraglio +servire +sestina +setola +settimana +sfacelo +sfaldare +sfamato +sfarzoso +sfaticato +sfera +sfida +sfilato +sfinge +sfocato +sfoderare +sfogo +sfoltire +sforzato +sfratto +sfruttato +sfuggito +sfumare +sfuso +sgabello +sgarbato +sgonfiare +sgorbio +sgrassato +sguardo +sibilo +siccome +sierra +sigla +signore +silenzio +sillaba +simbolo +simpatico +simulato +sinfonia +singolo +sinistro +sino +sintesi +sinusoide +sipario +sisma +sistole +situato +slitta +slogatura +sloveno +smarrito +smemorato +smentito +smeraldo +smilzo +smontare +smottato +smussato +snellire +snervato +snodo +sobbalzo +sobrio +soccorso +sociale +sodale +soffitto +sogno +soldato +solenne +solido +sollazzo +solo +solubile +solvente +somatico +somma +sonda +sonetto +sonnifero +sopire +soppeso +sopra +sorgere +sorpasso +sorriso +sorso +sorteggio +sorvolato +sospiro +sosta +sottile +spada +spalla +spargere +spatola +spavento +spazzola +specie +spedire +spegnere +spelatura +speranza +spessore +spettrale +spezzato +spia +spigoloso +spillato +spinoso +spirale +splendido +sportivo +sposo +spranga +sprecare +spronato +spruzzo +spuntino +squillo +sradicare +srotolato +stabile +stacco +staffa +stagnare +stampato +stantio +starnuto +stasera +statuto +stelo +steppa +sterzo +stiletto +stima +stirpe +stivale +stizzoso +stonato +storico +strappo +stregato +stridulo +strozzare +strutto +stuccare +stufo +stupendo +subentro +succoso +sudore +suggerito +sugo +sultano +suonare +superbo +supporto +surgelato +surrogato +sussurro +sutura +svagare +svedese +sveglio +svelare +svenuto +svezia +sviluppo +svista +svizzera +svolta +svuotare +tabacco +tabulato +tacciare +taciturno +tale +talismano +tampone +tannino +tara +tardivo +targato +tariffa +tarpare +tartaruga +tasto +tattico +taverna +tavolata +tazza +teca +tecnico +telefono +temerario +tempo +temuto +tendone +tenero +tensione +tentacolo +teorema +terme +terrazzo +terzetto +tesi +tesserato +testato +tetro +tettoia +tifare +tigella +timbro +tinto +tipico +tipografo +tiraggio +tiro +titanio +titolo +titubante +tizio +tizzone +toccare +tollerare +tolto +tombola +tomo +tonfo +tonsilla +topazio +topologia +toppa +torba +tornare +torrone +tortora +toscano +tossire +tostatura +totano +trabocco +trachea +trafila +tragedia +tralcio +tramonto +transito +trapano +trarre +trasloco +trattato +trave +treccia +tremolio +trespolo +tributo +tricheco +trifoglio +trillo +trincea +trio +tristezza +triturato +trivella +tromba +trono +troppo +trottola +trovare +truccato +tubatura +tuffato +tulipano +tumulto +tunisia +turbare +turchino +tuta +tutela +ubicato +uccello +uccisore +udire +uditivo +uffa +ufficio +uguale +ulisse +ultimato +umano +umile +umorismo +uncinetto +ungere +ungherese +unicorno +unificato +unisono +unitario +unte +uovo +upupa +uragano +urgenza +urlo +usanza +usato +uscito +usignolo +usuraio +utensile +utilizzo +utopia +vacante +vaccinato +vagabondo +vagliato +valanga +valgo +valico +valletta +valoroso +valutare +valvola +vampata +vangare +vanitoso +vano +vantaggio +vanvera +vapore +varano +varcato +variante +vasca +vedetta +vedova +veduto +vegetale +veicolo +velcro +velina +velluto +veloce +venato +vendemmia +vento +verace +verbale +vergogna +verifica +vero +verruca +verticale +vescica +vessillo +vestale +veterano +vetrina +vetusto +viandante +vibrante +vicenda +vichingo +vicinanza +vidimare +vigilia +vigneto +vigore +vile +villano +vimini +vincitore +viola +vipera +virgola +virologo +virulento +viscoso +visione +vispo +vissuto +visura +vita +vitello +vittima +vivanda +vivido +viziare +voce +voga +volatile +volere +volpe +voragine +vulcano +zampogna +zanna +zappato +zattera +zavorra +zefiro +zelante +zelo +zenzero +zerbino +zibetto +zinco +zircone +zitto +zolla +zotico +zucchero +zufolo +zulu +zuppa +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/japanese.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/japanese.go new file mode 100644 index 000000000..23a76a343 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/japanese.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/japanese.txt + // $ crc32 japanese.txt + // 0acc1419 + checksum := crc32.ChecksumIEEE([]byte(japanese)) + if fmt.Sprintf("%x", checksum) != "acc1419" { + panic(fmt.Sprintf("japanese checksum invalid: %x", checksum)) + } +} + +// Japanese is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/japanese.txt +var Japanese = strings.Split(strings.TrimSpace(japanese), "\n") +var japanese = `あいこくしん +あいさつ +あいだ +あおぞら +あかちゃん +あきる +あけがた +あける +あこがれる +あさい +あさひ +あしあと +あじわう +あずかる +あずき +あそぶ +あたえる +あたためる +あたりまえ +あたる +あつい +あつかう +あっしゅく +あつまり +あつめる +あてな +あてはまる +あひる +あぶら +あぶる +あふれる +あまい +あまど +あまやかす +あまり +あみもの +あめりか +あやまる +あゆむ +あらいぐま +あらし +あらすじ +あらためる +あらゆる +あらわす +ありがとう +あわせる +あわてる +あんい +あんがい +あんこ +あんぜん +あんてい +あんない +あんまり +いいだす +いおん +いがい +いがく +いきおい +いきなり +いきもの +いきる +いくじ +いくぶん +いけばな +いけん +いこう +いこく +いこつ +いさましい +いさん +いしき +いじゅう +いじょう +いじわる +いずみ +いずれ +いせい +いせえび +いせかい +いせき +いぜん +いそうろう +いそがしい +いだい +いだく +いたずら +いたみ +いたりあ +いちおう +いちじ +いちど +いちば +いちぶ +いちりゅう +いつか +いっしゅん +いっせい +いっそう +いったん +いっち +いってい +いっぽう +いてざ +いてん +いどう +いとこ +いない +いなか +いねむり +いのち +いのる +いはつ +いばる +いはん +いびき +いひん +いふく +いへん +いほう +いみん +いもうと +いもたれ +いもり +いやがる +いやす +いよかん +いよく +いらい +いらすと +いりぐち +いりょう +いれい +いれもの +いれる +いろえんぴつ +いわい +いわう +いわかん +いわば +いわゆる +いんげんまめ +いんさつ +いんしょう +いんよう +うえき +うえる +うおざ +うがい +うかぶ +うかべる +うきわ +うくらいな +うくれれ +うけたまわる +うけつけ +うけとる +うけもつ +うける +うごかす +うごく +うこん +うさぎ +うしなう +うしろがみ +うすい +うすぎ +うすぐらい +うすめる +うせつ +うちあわせ +うちがわ +うちき +うちゅう +うっかり +うつくしい +うったえる +うつる +うどん +うなぎ +うなじ +うなずく +うなる +うねる +うのう +うぶげ +うぶごえ +うまれる +うめる +うもう +うやまう +うよく +うらがえす +うらぐち +うらない +うりあげ +うりきれ +うるさい +うれしい +うれゆき +うれる +うろこ +うわき +うわさ +うんこう +うんちん +うんてん +うんどう +えいえん +えいが +えいきょう +えいご +えいせい +えいぶん +えいよう +えいわ +えおり +えがお +えがく +えきたい +えくせる +えしゃく +えすて +えつらん +えのぐ +えほうまき +えほん +えまき +えもじ +えもの +えらい +えらぶ +えりあ +えんえん +えんかい +えんぎ +えんげき +えんしゅう +えんぜつ +えんそく +えんちょう +えんとつ +おいかける +おいこす +おいしい +おいつく +おうえん +おうさま +おうじ +おうせつ +おうたい +おうふく +おうべい +おうよう +おえる +おおい +おおう +おおどおり +おおや +おおよそ +おかえり +おかず +おがむ +おかわり +おぎなう +おきる +おくさま +おくじょう +おくりがな +おくる +おくれる +おこす +おこなう +おこる +おさえる +おさない +おさめる +おしいれ +おしえる +おじぎ +おじさん +おしゃれ +おそらく +おそわる +おたがい +おたく +おだやか +おちつく +おっと +おつり +おでかけ +おとしもの +おとなしい +おどり +おどろかす +おばさん +おまいり +おめでとう +おもいで +おもう +おもたい +おもちゃ +おやつ +おやゆび +およぼす +おらんだ +おろす +おんがく +おんけい +おんしゃ +おんせん +おんだん +おんちゅう +おんどけい +かあつ +かいが +がいき +がいけん +がいこう +かいさつ +かいしゃ +かいすいよく +かいぜん +かいぞうど +かいつう +かいてん +かいとう +かいふく +がいへき +かいほう +かいよう +がいらい +かいわ +かえる +かおり +かかえる +かがく +かがし +かがみ +かくご +かくとく +かざる +がぞう +かたい +かたち +がちょう +がっきゅう +がっこう +がっさん +がっしょう +かなざわし +かのう +がはく +かぶか +かほう +かほご +かまう +かまぼこ +かめれおん +かゆい +かようび +からい +かるい +かろう +かわく +かわら +がんか +かんけい +かんこう +かんしゃ +かんそう +かんたん +かんち +がんばる +きあい +きあつ +きいろ +ぎいん +きうい +きうん +きえる +きおう +きおく +きおち +きおん +きかい +きかく +きかんしゃ +ききて +きくばり +きくらげ +きけんせい +きこう +きこえる +きこく +きさい +きさく +きさま +きさらぎ +ぎじかがく +ぎしき +ぎじたいけん +ぎじにってい +ぎじゅつしゃ +きすう +きせい +きせき +きせつ +きそう +きぞく +きぞん +きたえる +きちょう +きつえん +ぎっちり +きつつき +きつね +きてい +きどう +きどく +きない +きなが +きなこ +きぬごし +きねん +きのう +きのした +きはく +きびしい +きひん +きふく +きぶん +きぼう +きほん +きまる +きみつ +きむずかしい +きめる +きもだめし +きもち +きもの +きゃく +きやく +ぎゅうにく +きよう +きょうりゅう +きらい +きらく +きりん +きれい +きれつ +きろく +ぎろん +きわめる +ぎんいろ +きんかくじ +きんじょ +きんようび +ぐあい +くいず +くうかん +くうき +くうぐん +くうこう +ぐうせい +くうそう +ぐうたら +くうふく +くうぼ +くかん +くきょう +くげん +ぐこう +くさい +くさき +くさばな +くさる +くしゃみ +くしょう +くすのき +くすりゆび +くせげ +くせん +ぐたいてき +くださる +くたびれる +くちこみ +くちさき +くつした +ぐっすり +くつろぐ +くとうてん +くどく +くなん +くねくね +くのう +くふう +くみあわせ +くみたてる +くめる +くやくしょ +くらす +くらべる +くるま +くれる +くろう +くわしい +ぐんかん +ぐんしょく +ぐんたい +ぐんて +けあな +けいかく +けいけん +けいこ +けいさつ +げいじゅつ +けいたい +げいのうじん +けいれき +けいろ +けおとす +けおりもの +げきか +げきげん +げきだん +げきちん +げきとつ +げきは +げきやく +げこう +げこくじょう +げざい +けさき +げざん +けしき +けしごむ +けしょう +げすと +けたば +けちゃっぷ +けちらす +けつあつ +けつい +けつえき +けっこん +けつじょ +けっせき +けってい +けつまつ +げつようび +げつれい +けつろん +げどく +けとばす +けとる +けなげ +けなす +けなみ +けぬき +げねつ +けねん +けはい +げひん +けぶかい +げぼく +けまり +けみかる +けむし +けむり +けもの +けらい +けろけろ +けわしい +けんい +けんえつ +けんお +けんか +げんき +けんげん +けんこう +けんさく +けんしゅう +けんすう +げんそう +けんちく +けんてい +けんとう +けんない +けんにん +げんぶつ +けんま +けんみん +けんめい +けんらん +けんり +こあくま +こいぬ +こいびと +ごうい +こうえん +こうおん +こうかん +ごうきゅう +ごうけい +こうこう +こうさい +こうじ +こうすい +ごうせい +こうそく +こうたい +こうちゃ +こうつう +こうてい +こうどう +こうない +こうはい +ごうほう +ごうまん +こうもく +こうりつ +こえる +こおり +ごかい +ごがつ +ごかん +こくご +こくさい +こくとう +こくない +こくはく +こぐま +こけい +こける +ここのか +こころ +こさめ +こしつ +こすう +こせい +こせき +こぜん +こそだて +こたい +こたえる +こたつ +こちょう +こっか +こつこつ +こつばん +こつぶ +こてい +こてん +ことがら +ことし +ことば +ことり +こなごな +こねこね +このまま +このみ +このよ +ごはん +こひつじ +こふう +こふん +こぼれる +ごまあぶら +こまかい +ごますり +こまつな +こまる +こむぎこ +こもじ +こもち +こもの +こもん +こやく +こやま +こゆう +こゆび +こよい +こよう +こりる +これくしょん +ころっけ +こわもて +こわれる +こんいん +こんかい +こんき +こんしゅう +こんすい +こんだて +こんとん +こんなん +こんびに +こんぽん +こんまけ +こんや +こんれい +こんわく +ざいえき +さいかい +さいきん +ざいげん +ざいこ +さいしょ +さいせい +ざいたく +ざいちゅう +さいてき +ざいりょう +さうな +さかいし +さがす +さかな +さかみち +さがる +さぎょう +さくし +さくひん +さくら +さこく +さこつ +さずかる +ざせき +さたん +さつえい +ざつおん +ざっか +ざつがく +さっきょく +ざっし +さつじん +ざっそう +さつたば +さつまいも +さてい +さといも +さとう +さとおや +さとし +さとる +さのう +さばく +さびしい +さべつ +さほう +さほど +さます +さみしい +さみだれ +さむけ +さめる +さやえんどう +さゆう +さよう +さよく +さらだ +ざるそば +さわやか +さわる +さんいん +さんか +さんきゃく +さんこう +さんさい +ざんしょ +さんすう +さんせい +さんそ +さんち +さんま +さんみ +さんらん +しあい +しあげ +しあさって +しあわせ +しいく +しいん +しうち +しえい +しおけ +しかい +しかく +じかん +しごと +しすう +じだい +したうけ +したぎ +したて +したみ +しちょう +しちりん +しっかり +しつじ +しつもん +してい +してき +してつ +じてん +じどう +しなぎれ +しなもの +しなん +しねま +しねん +しのぐ +しのぶ +しはい +しばかり +しはつ +しはらい +しはん +しひょう +しふく +じぶん +しへい +しほう +しほん +しまう +しまる +しみん +しむける +じむしょ +しめい +しめる +しもん +しゃいん +しゃうん +しゃおん +じゃがいも +しやくしょ +しゃくほう +しゃけん +しゃこ +しゃざい +しゃしん +しゃせん +しゃそう +しゃたい +しゃちょう +しゃっきん +じゃま +しゃりん +しゃれい +じゆう +じゅうしょ +しゅくはく +じゅしん +しゅっせき +しゅみ +しゅらば +じゅんばん +しょうかい +しょくたく +しょっけん +しょどう +しょもつ +しらせる +しらべる +しんか +しんこう +じんじゃ +しんせいじ +しんちく +しんりん +すあげ +すあし +すあな +ずあん +すいえい +すいか +すいとう +ずいぶん +すいようび +すうがく +すうじつ +すうせん +すおどり +すきま +すくう +すくない +すける +すごい +すこし +ずさん +すずしい +すすむ +すすめる +すっかり +ずっしり +ずっと +すてき +すてる +すねる +すのこ +すはだ +すばらしい +ずひょう +ずぶぬれ +すぶり +すふれ +すべて +すべる +ずほう +すぼん +すまい +すめし +すもう +すやき +すらすら +するめ +すれちがう +すろっと +すわる +すんぜん +すんぽう +せあぶら +せいかつ +せいげん +せいじ +せいよう +せおう +せかいかん +せきにん +せきむ +せきゆ +せきらんうん +せけん +せこう +せすじ +せたい +せたけ +せっかく +せっきゃく +ぜっく +せっけん +せっこつ +せっさたくま +せつぞく +せつだん +せつでん +せっぱん +せつび +せつぶん +せつめい +せつりつ +せなか +せのび +せはば +せびろ +せぼね +せまい +せまる +せめる +せもたれ +せりふ +ぜんあく +せんい +せんえい +せんか +せんきょ +せんく +せんげん +ぜんご +せんさい +せんしゅ +せんすい +せんせい +せんぞ +せんたく +せんちょう +せんてい +せんとう +せんぬき +せんねん +せんぱい +ぜんぶ +ぜんぽう +せんむ +せんめんじょ +せんもん +せんやく +せんゆう +せんよう +ぜんら +ぜんりゃく +せんれい +せんろ +そあく +そいとげる +そいね +そうがんきょう +そうき +そうご +そうしん +そうだん +そうなん +そうび +そうめん +そうり +そえもの +そえん +そがい +そげき +そこう +そこそこ +そざい +そしな +そせい +そせん +そそぐ +そだてる +そつう +そつえん +そっかん +そつぎょう +そっけつ +そっこう +そっせん +そっと +そとがわ +そとづら +そなえる +そなた +そふぼ +そぼく +そぼろ +そまつ +そまる +そむく +そむりえ +そめる +そもそも +そよかぜ +そらまめ +そろう +そんかい +そんけい +そんざい +そんしつ +そんぞく +そんちょう +ぞんび +ぞんぶん +そんみん +たあい +たいいん +たいうん +たいえき +たいおう +だいがく +たいき +たいぐう +たいけん +たいこ +たいざい +だいじょうぶ +だいすき +たいせつ +たいそう +だいたい +たいちょう +たいてい +だいどころ +たいない +たいねつ +たいのう +たいはん +だいひょう +たいふう +たいへん +たいほ +たいまつばな +たいみんぐ +たいむ +たいめん +たいやき +たいよう +たいら +たいりょく +たいる +たいわん +たうえ +たえる +たおす +たおる +たおれる +たかい +たかね +たきび +たくさん +たこく +たこやき +たさい +たしざん +だじゃれ +たすける +たずさわる +たそがれ +たたかう +たたく +ただしい +たたみ +たちばな +だっかい +だっきゃく +だっこ +だっしゅつ +だったい +たてる +たとえる +たなばた +たにん +たぬき +たのしみ +たはつ +たぶん +たべる +たぼう +たまご +たまる +だむる +ためいき +ためす +ためる +たもつ +たやすい +たよる +たらす +たりきほんがん +たりょう +たりる +たると +たれる +たれんと +たろっと +たわむれる +だんあつ +たんい +たんおん +たんか +たんき +たんけん +たんご +たんさん +たんじょうび +だんせい +たんそく +たんたい +だんち +たんてい +たんとう +だんな +たんにん +だんねつ +たんのう +たんぴん +だんぼう +たんまつ +たんめい +だんれつ +だんろ +だんわ +ちあい +ちあん +ちいき +ちいさい +ちえん +ちかい +ちから +ちきゅう +ちきん +ちけいず +ちけん +ちこく +ちさい +ちしき +ちしりょう +ちせい +ちそう +ちたい +ちたん +ちちおや +ちつじょ +ちてき +ちてん +ちぬき +ちぬり +ちのう +ちひょう +ちへいせん +ちほう +ちまた +ちみつ +ちみどろ +ちめいど +ちゃんこなべ +ちゅうい +ちゆりょく +ちょうし +ちょさくけん +ちらし +ちらみ +ちりがみ +ちりょう +ちるど +ちわわ +ちんたい +ちんもく +ついか +ついたち +つうか +つうじょう +つうはん +つうわ +つかう +つかれる +つくね +つくる +つけね +つける +つごう +つたえる +つづく +つつじ +つつむ +つとめる +つながる +つなみ +つねづね +つのる +つぶす +つまらない +つまる +つみき +つめたい +つもり +つもる +つよい +つるぼ +つるみく +つわもの +つわり +てあし +てあて +てあみ +ていおん +ていか +ていき +ていけい +ていこく +ていさつ +ていし +ていせい +ていたい +ていど +ていねい +ていひょう +ていへん +ていぼう +てうち +ておくれ +てきとう +てくび +でこぼこ +てさぎょう +てさげ +てすり +てそう +てちがい +てちょう +てつがく +てつづき +でっぱ +てつぼう +てつや +でぬかえ +てぬき +てぬぐい +てのひら +てはい +てぶくろ +てふだ +てほどき +てほん +てまえ +てまきずし +てみじか +てみやげ +てらす +てれび +てわけ +てわたし +でんあつ +てんいん +てんかい +てんき +てんぐ +てんけん +てんごく +てんさい +てんし +てんすう +でんち +てんてき +てんとう +てんない +てんぷら +てんぼうだい +てんめつ +てんらんかい +でんりょく +でんわ +どあい +といれ +どうかん +とうきゅう +どうぐ +とうし +とうむぎ +とおい +とおか +とおく +とおす +とおる +とかい +とかす +ときおり +ときどき +とくい +とくしゅう +とくてん +とくに +とくべつ +とけい +とける +とこや +とさか +としょかん +とそう +とたん +とちゅう +とっきゅう +とっくん +とつぜん +とつにゅう +とどける +ととのえる +とない +となえる +となり +とのさま +とばす +どぶがわ +とほう +とまる +とめる +ともだち +ともる +どようび +とらえる +とんかつ +どんぶり +ないかく +ないこう +ないしょ +ないす +ないせん +ないそう +なおす +ながい +なくす +なげる +なこうど +なさけ +なたでここ +なっとう +なつやすみ +ななおし +なにごと +なにもの +なにわ +なのか +なふだ +なまいき +なまえ +なまみ +なみだ +なめらか +なめる +なやむ +ならう +ならび +ならぶ +なれる +なわとび +なわばり +にあう +にいがた +にうけ +におい +にかい +にがて +にきび +にくしみ +にくまん +にげる +にさんかたんそ +にしき +にせもの +にちじょう +にちようび +にっか +にっき +にっけい +にっこう +にっさん +にっしょく +にっすう +にっせき +にってい +になう +にほん +にまめ +にもつ +にやり +にゅういん +にりんしゃ +にわとり +にんい +にんか +にんき +にんげん +にんしき +にんずう +にんそう +にんたい +にんち +にんてい +にんにく +にんぷ +にんまり +にんむ +にんめい +にんよう +ぬいくぎ +ぬかす +ぬぐいとる +ぬぐう +ぬくもり +ぬすむ +ぬまえび +ぬめり +ぬらす +ぬんちゃく +ねあげ +ねいき +ねいる +ねいろ +ねぐせ +ねくたい +ねくら +ねこぜ +ねこむ +ねさげ +ねすごす +ねそべる +ねだん +ねつい +ねっしん +ねつぞう +ねったいぎょ +ねぶそく +ねふだ +ねぼう +ねほりはほり +ねまき +ねまわし +ねみみ +ねむい +ねむたい +ねもと +ねらう +ねわざ +ねんいり +ねんおし +ねんかん +ねんきん +ねんぐ +ねんざ +ねんし +ねんちゃく +ねんど +ねんぴ +ねんぶつ +ねんまつ +ねんりょう +ねんれい +のいず +のおづま +のがす +のきなみ +のこぎり +のこす +のこる +のせる +のぞく +のぞむ +のたまう +のちほど +のっく +のばす +のはら +のべる +のぼる +のみもの +のやま +のらいぬ +のらねこ +のりもの +のりゆき +のれん +のんき +ばあい +はあく +ばあさん +ばいか +ばいく +はいけん +はいご +はいしん +はいすい +はいせん +はいそう +はいち +ばいばい +はいれつ +はえる +はおる +はかい +ばかり +はかる +はくしゅ +はけん +はこぶ +はさみ +はさん +はしご +ばしょ +はしる +はせる +ぱそこん +はそん +はたん +はちみつ +はつおん +はっかく +はづき +はっきり +はっくつ +はっけん +はっこう +はっさん +はっしん +はったつ +はっちゅう +はってん +はっぴょう +はっぽう +はなす +はなび +はにかむ +はぶらし +はみがき +はむかう +はめつ +はやい +はやし +はらう +はろうぃん +はわい +はんい +はんえい +はんおん +はんかく +はんきょう +ばんぐみ +はんこ +はんしゃ +はんすう +はんだん +ぱんち +ぱんつ +はんてい +はんとし +はんのう +はんぱ +はんぶん +はんぺん +はんぼうき +はんめい +はんらん +はんろん +ひいき +ひうん +ひえる +ひかく +ひかり +ひかる +ひかん +ひくい +ひけつ +ひこうき +ひこく +ひさい +ひさしぶり +ひさん +びじゅつかん +ひしょ +ひそか +ひそむ +ひたむき +ひだり +ひたる +ひつぎ +ひっこし +ひっし +ひつじゅひん +ひっす +ひつぜん +ぴったり +ぴっちり +ひつよう +ひてい +ひとごみ +ひなまつり +ひなん +ひねる +ひはん +ひびく +ひひょう +ひほう +ひまわり +ひまん +ひみつ +ひめい +ひめじし +ひやけ +ひやす +ひよう +びょうき +ひらがな +ひらく +ひりつ +ひりょう +ひるま +ひるやすみ +ひれい +ひろい +ひろう +ひろき +ひろゆき +ひんかく +ひんけつ +ひんこん +ひんしゅ +ひんそう +ぴんち +ひんぱん +びんぼう +ふあん +ふいうち +ふうけい +ふうせん +ぷうたろう +ふうとう +ふうふ +ふえる +ふおん +ふかい +ふきん +ふくざつ +ふくぶくろ +ふこう +ふさい +ふしぎ +ふじみ +ふすま +ふせい +ふせぐ +ふそく +ぶたにく +ふたん +ふちょう +ふつう +ふつか +ふっかつ +ふっき +ふっこく +ぶどう +ふとる +ふとん +ふのう +ふはい +ふひょう +ふへん +ふまん +ふみん +ふめつ +ふめん +ふよう +ふりこ +ふりる +ふるい +ふんいき +ぶんがく +ぶんぐ +ふんしつ +ぶんせき +ふんそう +ぶんぽう +へいあん +へいおん +へいがい +へいき +へいげん +へいこう +へいさ +へいしゃ +へいせつ +へいそ +へいたく +へいてん +へいねつ +へいわ +へきが +へこむ +べにいろ +べにしょうが +へらす +へんかん +べんきょう +べんごし +へんさい +へんたい +べんり +ほあん +ほいく +ぼうぎょ +ほうこく +ほうそう +ほうほう +ほうもん +ほうりつ +ほえる +ほおん +ほかん +ほきょう +ぼきん +ほくろ +ほけつ +ほけん +ほこう +ほこる +ほしい +ほしつ +ほしゅ +ほしょう +ほせい +ほそい +ほそく +ほたて +ほたる +ぽちぶくろ +ほっきょく +ほっさ +ほったん +ほとんど +ほめる +ほんい +ほんき +ほんけ +ほんしつ +ほんやく +まいにち +まかい +まかせる +まがる +まける +まこと +まさつ +まじめ +ますく +まぜる +まつり +まとめ +まなぶ +まぬけ +まねく +まほう +まもる +まゆげ +まよう +まろやか +まわす +まわり +まわる +まんが +まんきつ +まんぞく +まんなか +みいら +みうち +みえる +みがく +みかた +みかん +みけん +みこん +みじかい +みすい +みすえる +みせる +みっか +みつかる +みつける +みてい +みとめる +みなと +みなみかさい +みねらる +みのう +みのがす +みほん +みもと +みやげ +みらい +みりょく +みわく +みんか +みんぞく +むいか +むえき +むえん +むかい +むかう +むかえ +むかし +むぎちゃ +むける +むげん +むさぼる +むしあつい +むしば +むじゅん +むしろ +むすう +むすこ +むすぶ +むすめ +むせる +むせん +むちゅう +むなしい +むのう +むやみ +むよう +むらさき +むりょう +むろん +めいあん +めいうん +めいえん +めいかく +めいきょく +めいさい +めいし +めいそう +めいぶつ +めいれい +めいわく +めぐまれる +めざす +めした +めずらしい +めだつ +めまい +めやす +めんきょ +めんせき +めんどう +もうしあげる +もうどうけん +もえる +もくし +もくてき +もくようび +もちろん +もどる +もらう +もんく +もんだい +やおや +やける +やさい +やさしい +やすい +やすたろう +やすみ +やせる +やそう +やたい +やちん +やっと +やっぱり +やぶる +やめる +ややこしい +やよい +やわらかい +ゆうき +ゆうびんきょく +ゆうべ +ゆうめい +ゆけつ +ゆしゅつ +ゆせん +ゆそう +ゆたか +ゆちゃく +ゆでる +ゆにゅう +ゆびわ +ゆらい +ゆれる +ようい +ようか +ようきゅう +ようじ +ようす +ようちえん +よかぜ +よかん +よきん +よくせい +よくぼう +よけい +よごれる +よさん +よしゅう +よそう +よそく +よっか +よてい +よどがわく +よねつ +よやく +よゆう +よろこぶ +よろしい +らいう +らくがき +らくご +らくさつ +らくだ +らしんばん +らせん +らぞく +らたい +らっか +られつ +りえき +りかい +りきさく +りきせつ +りくぐん +りくつ +りけん +りこう +りせい +りそう +りそく +りてん +りねん +りゆう +りゅうがく +りよう +りょうり +りょかん +りょくちゃ +りょこう +りりく +りれき +りろん +りんご +るいけい +るいさい +るいじ +るいせき +るすばん +るりがわら +れいかん +れいぎ +れいせい +れいぞうこ +れいとう +れいぼう +れきし +れきだい +れんあい +れんけい +れんこん +れんさい +れんしゅう +れんぞく +れんらく +ろうか +ろうご +ろうじん +ろうそく +ろくが +ろこつ +ろじうら +ろしゅつ +ろせん +ろてん +ろめん +ろれつ +ろんぎ +ろんぱ +ろんぶん +ろんり +わかす +わかめ +わかやま +わかれる +わしつ +わじまし +わすれもの +わらう +われる +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/korean.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/korean.go new file mode 100644 index 000000000..1d3177563 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/korean.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/korean.txt + // $ crc32 korean.txt + // 4ef461eb + checksum := crc32.ChecksumIEEE([]byte(korean)) + if fmt.Sprintf("%x", checksum) != "4ef461eb" { + panic("korean checksum invalid") + } +} + +// Korean is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/korean.txt +var Korean = strings.Split(strings.TrimSpace(korean), "\n") +var korean = `가격 +가끔 +가난 +가능 +가득 +가르침 +가뭄 +가방 +가상 +가슴 +가운데 +가을 +가이드 +가입 +가장 +가정 +가족 +가죽 +각오 +각자 +간격 +간부 +간섭 +간장 +간접 +간판 +갈등 +갈비 +갈색 +갈증 +감각 +감기 +감소 +감수성 +감자 +감정 +갑자기 +강남 +강당 +강도 +강력히 +강변 +강북 +강사 +강수량 +강아지 +강원도 +강의 +강제 +강조 +같이 +개구리 +개나리 +개방 +개별 +개선 +개성 +개인 +객관적 +거실 +거액 +거울 +거짓 +거품 +걱정 +건강 +건물 +건설 +건조 +건축 +걸음 +검사 +검토 +게시판 +게임 +겨울 +견해 +결과 +결국 +결론 +결석 +결승 +결심 +결정 +결혼 +경계 +경고 +경기 +경력 +경복궁 +경비 +경상도 +경영 +경우 +경쟁 +경제 +경주 +경찰 +경치 +경향 +경험 +계곡 +계단 +계란 +계산 +계속 +계약 +계절 +계층 +계획 +고객 +고구려 +고궁 +고급 +고등학생 +고무신 +고민 +고양이 +고장 +고전 +고집 +고춧가루 +고통 +고향 +곡식 +골목 +골짜기 +골프 +공간 +공개 +공격 +공군 +공급 +공기 +공동 +공무원 +공부 +공사 +공식 +공업 +공연 +공원 +공장 +공짜 +공책 +공통 +공포 +공항 +공휴일 +과목 +과일 +과장 +과정 +과학 +관객 +관계 +관광 +관념 +관람 +관련 +관리 +관습 +관심 +관점 +관찰 +광경 +광고 +광장 +광주 +괴로움 +굉장히 +교과서 +교문 +교복 +교실 +교양 +교육 +교장 +교직 +교통 +교환 +교훈 +구경 +구름 +구멍 +구별 +구분 +구석 +구성 +구속 +구역 +구입 +구청 +구체적 +국가 +국기 +국내 +국립 +국물 +국민 +국수 +국어 +국왕 +국적 +국제 +국회 +군대 +군사 +군인 +궁극적 +권리 +권위 +권투 +귀국 +귀신 +규정 +규칙 +균형 +그날 +그냥 +그늘 +그러나 +그룹 +그릇 +그림 +그제서야 +그토록 +극복 +극히 +근거 +근교 +근래 +근로 +근무 +근본 +근원 +근육 +근처 +글씨 +글자 +금강산 +금고 +금년 +금메달 +금액 +금연 +금요일 +금지 +긍정적 +기간 +기관 +기념 +기능 +기독교 +기둥 +기록 +기름 +기법 +기본 +기분 +기쁨 +기숙사 +기술 +기억 +기업 +기온 +기운 +기원 +기적 +기준 +기침 +기혼 +기획 +긴급 +긴장 +길이 +김밥 +김치 +김포공항 +깍두기 +깜빡 +깨달음 +깨소금 +껍질 +꼭대기 +꽃잎 +나들이 +나란히 +나머지 +나물 +나침반 +나흘 +낙엽 +난방 +날개 +날씨 +날짜 +남녀 +남대문 +남매 +남산 +남자 +남편 +남학생 +낭비 +낱말 +내년 +내용 +내일 +냄비 +냄새 +냇물 +냉동 +냉면 +냉방 +냉장고 +넥타이 +넷째 +노동 +노란색 +노력 +노인 +녹음 +녹차 +녹화 +논리 +논문 +논쟁 +놀이 +농구 +농담 +농민 +농부 +농업 +농장 +농촌 +높이 +눈동자 +눈물 +눈썹 +뉴욕 +느낌 +늑대 +능동적 +능력 +다방 +다양성 +다음 +다이어트 +다행 +단계 +단골 +단독 +단맛 +단순 +단어 +단위 +단점 +단체 +단추 +단편 +단풍 +달걀 +달러 +달력 +달리 +닭고기 +담당 +담배 +담요 +담임 +답변 +답장 +당근 +당분간 +당연히 +당장 +대규모 +대낮 +대단히 +대답 +대도시 +대략 +대량 +대륙 +대문 +대부분 +대신 +대응 +대장 +대전 +대접 +대중 +대책 +대출 +대충 +대통령 +대학 +대한민국 +대합실 +대형 +덩어리 +데이트 +도대체 +도덕 +도둑 +도망 +도서관 +도심 +도움 +도입 +도자기 +도저히 +도전 +도중 +도착 +독감 +독립 +독서 +독일 +독창적 +동화책 +뒷모습 +뒷산 +딸아이 +마누라 +마늘 +마당 +마라톤 +마련 +마무리 +마사지 +마약 +마요네즈 +마을 +마음 +마이크 +마중 +마지막 +마찬가지 +마찰 +마흔 +막걸리 +막내 +막상 +만남 +만두 +만세 +만약 +만일 +만점 +만족 +만화 +많이 +말기 +말씀 +말투 +맘대로 +망원경 +매년 +매달 +매력 +매번 +매스컴 +매일 +매장 +맥주 +먹이 +먼저 +먼지 +멀리 +메일 +며느리 +며칠 +면담 +멸치 +명단 +명령 +명예 +명의 +명절 +명칭 +명함 +모금 +모니터 +모델 +모든 +모범 +모습 +모양 +모임 +모조리 +모집 +모퉁이 +목걸이 +목록 +목사 +목소리 +목숨 +목적 +목표 +몰래 +몸매 +몸무게 +몸살 +몸속 +몸짓 +몸통 +몹시 +무관심 +무궁화 +무더위 +무덤 +무릎 +무슨 +무엇 +무역 +무용 +무조건 +무지개 +무척 +문구 +문득 +문법 +문서 +문제 +문학 +문화 +물가 +물건 +물결 +물고기 +물론 +물리학 +물음 +물질 +물체 +미국 +미디어 +미사일 +미술 +미역 +미용실 +미움 +미인 +미팅 +미혼 +민간 +민족 +민주 +믿음 +밀가루 +밀리미터 +밑바닥 +바가지 +바구니 +바나나 +바늘 +바닥 +바닷가 +바람 +바이러스 +바탕 +박물관 +박사 +박수 +반대 +반드시 +반말 +반발 +반성 +반응 +반장 +반죽 +반지 +반찬 +받침 +발가락 +발걸음 +발견 +발달 +발레 +발목 +발바닥 +발생 +발음 +발자국 +발전 +발톱 +발표 +밤하늘 +밥그릇 +밥맛 +밥상 +밥솥 +방금 +방면 +방문 +방바닥 +방법 +방송 +방식 +방안 +방울 +방지 +방학 +방해 +방향 +배경 +배꼽 +배달 +배드민턴 +백두산 +백색 +백성 +백인 +백제 +백화점 +버릇 +버섯 +버튼 +번개 +번역 +번지 +번호 +벌금 +벌레 +벌써 +범위 +범인 +범죄 +법률 +법원 +법적 +법칙 +베이징 +벨트 +변경 +변동 +변명 +변신 +변호사 +변화 +별도 +별명 +별일 +병실 +병아리 +병원 +보관 +보너스 +보라색 +보람 +보름 +보상 +보안 +보자기 +보장 +보전 +보존 +보통 +보편적 +보험 +복도 +복사 +복숭아 +복습 +볶음 +본격적 +본래 +본부 +본사 +본성 +본인 +본질 +볼펜 +봉사 +봉지 +봉투 +부근 +부끄러움 +부담 +부동산 +부문 +부분 +부산 +부상 +부엌 +부인 +부작용 +부장 +부정 +부족 +부지런히 +부친 +부탁 +부품 +부회장 +북부 +북한 +분노 +분량 +분리 +분명 +분석 +분야 +분위기 +분필 +분홍색 +불고기 +불과 +불교 +불꽃 +불만 +불법 +불빛 +불안 +불이익 +불행 +브랜드 +비극 +비난 +비닐 +비둘기 +비디오 +비로소 +비만 +비명 +비밀 +비바람 +비빔밥 +비상 +비용 +비율 +비중 +비타민 +비판 +빌딩 +빗물 +빗방울 +빗줄기 +빛깔 +빨간색 +빨래 +빨리 +사건 +사계절 +사나이 +사냥 +사람 +사랑 +사립 +사모님 +사물 +사방 +사상 +사생활 +사설 +사슴 +사실 +사업 +사용 +사월 +사장 +사전 +사진 +사촌 +사춘기 +사탕 +사투리 +사흘 +산길 +산부인과 +산업 +산책 +살림 +살인 +살짝 +삼계탕 +삼국 +삼십 +삼월 +삼촌 +상관 +상금 +상대 +상류 +상반기 +상상 +상식 +상업 +상인 +상자 +상점 +상처 +상추 +상태 +상표 +상품 +상황 +새벽 +색깔 +색연필 +생각 +생명 +생물 +생방송 +생산 +생선 +생신 +생일 +생활 +서랍 +서른 +서명 +서민 +서비스 +서양 +서울 +서적 +서점 +서쪽 +서클 +석사 +석유 +선거 +선물 +선배 +선생 +선수 +선원 +선장 +선전 +선택 +선풍기 +설거지 +설날 +설렁탕 +설명 +설문 +설사 +설악산 +설치 +설탕 +섭씨 +성공 +성당 +성명 +성별 +성인 +성장 +성적 +성질 +성함 +세금 +세미나 +세상 +세월 +세종대왕 +세탁 +센터 +센티미터 +셋째 +소규모 +소극적 +소금 +소나기 +소년 +소득 +소망 +소문 +소설 +소속 +소아과 +소용 +소원 +소음 +소중히 +소지품 +소질 +소풍 +소형 +속담 +속도 +속옷 +손가락 +손길 +손녀 +손님 +손등 +손목 +손뼉 +손실 +손질 +손톱 +손해 +솔직히 +솜씨 +송아지 +송이 +송편 +쇠고기 +쇼핑 +수건 +수년 +수단 +수돗물 +수동적 +수면 +수명 +수박 +수상 +수석 +수술 +수시로 +수업 +수염 +수영 +수입 +수준 +수집 +수출 +수컷 +수필 +수학 +수험생 +수화기 +숙녀 +숙소 +숙제 +순간 +순서 +순수 +순식간 +순위 +숟가락 +술병 +술집 +숫자 +스님 +스물 +스스로 +스승 +스웨터 +스위치 +스케이트 +스튜디오 +스트레스 +스포츠 +슬쩍 +슬픔 +습관 +습기 +승객 +승리 +승부 +승용차 +승진 +시각 +시간 +시골 +시금치 +시나리오 +시댁 +시리즈 +시멘트 +시민 +시부모 +시선 +시설 +시스템 +시아버지 +시어머니 +시월 +시인 +시일 +시작 +시장 +시절 +시점 +시중 +시즌 +시집 +시청 +시합 +시험 +식구 +식기 +식당 +식량 +식료품 +식물 +식빵 +식사 +식생활 +식초 +식탁 +식품 +신고 +신규 +신념 +신문 +신발 +신비 +신사 +신세 +신용 +신제품 +신청 +신체 +신화 +실감 +실내 +실력 +실례 +실망 +실수 +실습 +실시 +실장 +실정 +실질적 +실천 +실체 +실컷 +실태 +실패 +실험 +실현 +심리 +심부름 +심사 +심장 +심정 +심판 +쌍둥이 +씨름 +씨앗 +아가씨 +아나운서 +아드님 +아들 +아쉬움 +아스팔트 +아시아 +아울러 +아저씨 +아줌마 +아직 +아침 +아파트 +아프리카 +아픔 +아홉 +아흔 +악기 +악몽 +악수 +안개 +안경 +안과 +안내 +안녕 +안동 +안방 +안부 +안주 +알루미늄 +알코올 +암시 +암컷 +압력 +앞날 +앞문 +애인 +애정 +액수 +앨범 +야간 +야단 +야옹 +약간 +약국 +약속 +약수 +약점 +약품 +약혼녀 +양념 +양력 +양말 +양배추 +양주 +양파 +어둠 +어려움 +어른 +어젯밤 +어쨌든 +어쩌다가 +어쩐지 +언니 +언덕 +언론 +언어 +얼굴 +얼른 +얼음 +얼핏 +엄마 +업무 +업종 +업체 +엉덩이 +엉망 +엉터리 +엊그제 +에너지 +에어컨 +엔진 +여건 +여고생 +여관 +여군 +여권 +여대생 +여덟 +여동생 +여든 +여론 +여름 +여섯 +여성 +여왕 +여인 +여전히 +여직원 +여학생 +여행 +역사 +역시 +역할 +연결 +연구 +연극 +연기 +연락 +연설 +연세 +연속 +연습 +연애 +연예인 +연인 +연장 +연주 +연출 +연필 +연합 +연휴 +열기 +열매 +열쇠 +열심히 +열정 +열차 +열흘 +염려 +엽서 +영국 +영남 +영상 +영양 +영역 +영웅 +영원히 +영하 +영향 +영혼 +영화 +옆구리 +옆방 +옆집 +예감 +예금 +예방 +예산 +예상 +예선 +예술 +예습 +예식장 +예약 +예전 +예절 +예정 +예컨대 +옛날 +오늘 +오락 +오랫동안 +오렌지 +오로지 +오른발 +오븐 +오십 +오염 +오월 +오전 +오직 +오징어 +오페라 +오피스텔 +오히려 +옥상 +옥수수 +온갖 +온라인 +온몸 +온종일 +온통 +올가을 +올림픽 +올해 +옷차림 +와이셔츠 +와인 +완성 +완전 +왕비 +왕자 +왜냐하면 +왠지 +외갓집 +외국 +외로움 +외삼촌 +외출 +외침 +외할머니 +왼발 +왼손 +왼쪽 +요금 +요일 +요즘 +요청 +용기 +용서 +용어 +우산 +우선 +우승 +우연히 +우정 +우체국 +우편 +운동 +운명 +운반 +운전 +운행 +울산 +울음 +움직임 +웃어른 +웃음 +워낙 +원고 +원래 +원서 +원숭이 +원인 +원장 +원피스 +월급 +월드컵 +월세 +월요일 +웨이터 +위반 +위법 +위성 +위원 +위험 +위협 +윗사람 +유난히 +유럽 +유명 +유물 +유산 +유적 +유치원 +유학 +유행 +유형 +육군 +육상 +육십 +육체 +은행 +음력 +음료 +음반 +음성 +음식 +음악 +음주 +의견 +의논 +의문 +의복 +의식 +의심 +의외로 +의욕 +의원 +의학 +이것 +이곳 +이념 +이놈 +이달 +이대로 +이동 +이렇게 +이력서 +이론적 +이름 +이민 +이발소 +이별 +이불 +이빨 +이상 +이성 +이슬 +이야기 +이용 +이웃 +이월 +이윽고 +이익 +이전 +이중 +이튿날 +이틀 +이혼 +인간 +인격 +인공 +인구 +인근 +인기 +인도 +인류 +인물 +인생 +인쇄 +인연 +인원 +인재 +인종 +인천 +인체 +인터넷 +인하 +인형 +일곱 +일기 +일단 +일대 +일등 +일반 +일본 +일부 +일상 +일생 +일손 +일요일 +일월 +일정 +일종 +일주일 +일찍 +일체 +일치 +일행 +일회용 +임금 +임무 +입대 +입력 +입맛 +입사 +입술 +입시 +입원 +입장 +입학 +자가용 +자격 +자극 +자동 +자랑 +자부심 +자식 +자신 +자연 +자원 +자율 +자전거 +자정 +자존심 +자판 +작가 +작년 +작성 +작업 +작용 +작은딸 +작품 +잔디 +잔뜩 +잔치 +잘못 +잠깐 +잠수함 +잠시 +잠옷 +잠자리 +잡지 +장관 +장군 +장기간 +장래 +장례 +장르 +장마 +장면 +장모 +장미 +장비 +장사 +장소 +장식 +장애인 +장인 +장점 +장차 +장학금 +재능 +재빨리 +재산 +재생 +재작년 +재정 +재채기 +재판 +재학 +재활용 +저것 +저고리 +저곳 +저녁 +저런 +저렇게 +저번 +저울 +저절로 +저축 +적극 +적당히 +적성 +적용 +적응 +전개 +전공 +전기 +전달 +전라도 +전망 +전문 +전반 +전부 +전세 +전시 +전용 +전자 +전쟁 +전주 +전철 +전체 +전통 +전혀 +전후 +절대 +절망 +절반 +절약 +절차 +점검 +점수 +점심 +점원 +점점 +점차 +접근 +접시 +접촉 +젓가락 +정거장 +정도 +정류장 +정리 +정말 +정면 +정문 +정반대 +정보 +정부 +정비 +정상 +정성 +정오 +정원 +정장 +정지 +정치 +정확히 +제공 +제과점 +제대로 +제목 +제발 +제법 +제삿날 +제안 +제일 +제작 +제주도 +제출 +제품 +제한 +조각 +조건 +조금 +조깅 +조명 +조미료 +조상 +조선 +조용히 +조절 +조정 +조직 +존댓말 +존재 +졸업 +졸음 +종교 +종로 +종류 +종소리 +종업원 +종종 +종합 +좌석 +죄인 +주관적 +주름 +주말 +주머니 +주먹 +주문 +주민 +주방 +주변 +주식 +주인 +주일 +주장 +주전자 +주택 +준비 +줄거리 +줄기 +줄무늬 +중간 +중계방송 +중국 +중년 +중단 +중독 +중반 +중부 +중세 +중소기업 +중순 +중앙 +중요 +중학교 +즉석 +즉시 +즐거움 +증가 +증거 +증권 +증상 +증세 +지각 +지갑 +지경 +지극히 +지금 +지급 +지능 +지름길 +지리산 +지방 +지붕 +지식 +지역 +지우개 +지원 +지적 +지점 +지진 +지출 +직선 +직업 +직원 +직장 +진급 +진동 +진로 +진료 +진리 +진짜 +진찰 +진출 +진통 +진행 +질문 +질병 +질서 +짐작 +집단 +집안 +집중 +짜증 +찌꺼기 +차남 +차라리 +차량 +차림 +차별 +차선 +차츰 +착각 +찬물 +찬성 +참가 +참기름 +참새 +참석 +참여 +참외 +참조 +찻잔 +창가 +창고 +창구 +창문 +창밖 +창작 +창조 +채널 +채점 +책가방 +책방 +책상 +책임 +챔피언 +처벌 +처음 +천국 +천둥 +천장 +천재 +천천히 +철도 +철저히 +철학 +첫날 +첫째 +청년 +청바지 +청소 +청춘 +체계 +체력 +체온 +체육 +체중 +체험 +초등학생 +초반 +초밥 +초상화 +초순 +초여름 +초원 +초저녁 +초점 +초청 +초콜릿 +촛불 +총각 +총리 +총장 +촬영 +최근 +최상 +최선 +최신 +최악 +최종 +추석 +추억 +추진 +추천 +추측 +축구 +축소 +축제 +축하 +출근 +출발 +출산 +출신 +출연 +출입 +출장 +출판 +충격 +충고 +충돌 +충분히 +충청도 +취업 +취직 +취향 +치약 +친구 +친척 +칠십 +칠월 +칠판 +침대 +침묵 +침실 +칫솔 +칭찬 +카메라 +카운터 +칼국수 +캐릭터 +캠퍼스 +캠페인 +커튼 +컨디션 +컬러 +컴퓨터 +코끼리 +코미디 +콘서트 +콜라 +콤플렉스 +콩나물 +쾌감 +쿠데타 +크림 +큰길 +큰딸 +큰소리 +큰아들 +큰어머니 +큰일 +큰절 +클래식 +클럽 +킬로 +타입 +타자기 +탁구 +탁자 +탄생 +태권도 +태양 +태풍 +택시 +탤런트 +터널 +터미널 +테니스 +테스트 +테이블 +텔레비전 +토론 +토마토 +토요일 +통계 +통과 +통로 +통신 +통역 +통일 +통장 +통제 +통증 +통합 +통화 +퇴근 +퇴원 +퇴직금 +튀김 +트럭 +특급 +특별 +특성 +특수 +특징 +특히 +튼튼히 +티셔츠 +파란색 +파일 +파출소 +판결 +판단 +판매 +판사 +팔십 +팔월 +팝송 +패션 +팩스 +팩시밀리 +팬티 +퍼센트 +페인트 +편견 +편의 +편지 +편히 +평가 +평균 +평생 +평소 +평양 +평일 +평화 +포스터 +포인트 +포장 +포함 +표면 +표정 +표준 +표현 +품목 +품질 +풍경 +풍속 +풍습 +프랑스 +프린터 +플라스틱 +피곤 +피망 +피아노 +필름 +필수 +필요 +필자 +필통 +핑계 +하느님 +하늘 +하드웨어 +하룻밤 +하반기 +하숙집 +하순 +하여튼 +하지만 +하천 +하품 +하필 +학과 +학교 +학급 +학기 +학년 +학력 +학번 +학부모 +학비 +학생 +학술 +학습 +학용품 +학원 +학위 +학자 +학점 +한계 +한글 +한꺼번에 +한낮 +한눈 +한동안 +한때 +한라산 +한마디 +한문 +한번 +한복 +한식 +한여름 +한쪽 +할머니 +할아버지 +할인 +함께 +함부로 +합격 +합리적 +항공 +항구 +항상 +항의 +해결 +해군 +해답 +해당 +해물 +해석 +해설 +해수욕장 +해안 +핵심 +핸드백 +햄버거 +햇볕 +햇살 +행동 +행복 +행사 +행운 +행위 +향기 +향상 +향수 +허락 +허용 +헬기 +현관 +현금 +현대 +현상 +현실 +현장 +현재 +현지 +혈액 +협력 +형부 +형사 +형수 +형식 +형제 +형태 +형편 +혜택 +호기심 +호남 +호랑이 +호박 +호텔 +호흡 +혹시 +홀로 +홈페이지 +홍보 +홍수 +홍차 +화면 +화분 +화살 +화요일 +화장 +화학 +확보 +확인 +확장 +확정 +환갑 +환경 +환영 +환율 +환자 +활기 +활동 +활발히 +활용 +활짝 +회견 +회관 +회복 +회색 +회원 +회장 +회전 +횟수 +횡단보도 +효율적 +후반 +후춧가루 +훈련 +훨씬 +휴식 +휴일 +흉내 +흐름 +흑백 +흑인 +흔적 +흔히 +흥미 +흥분 +희곡 +희망 +희생 +흰색 +힘껏 +` diff --git a/vendor/github.com/tyler-smith/go-bip39/wordlists/spanish.go b/vendor/github.com/tyler-smith/go-bip39/wordlists/spanish.go new file mode 100644 index 000000000..ad76da976 --- /dev/null +++ b/vendor/github.com/tyler-smith/go-bip39/wordlists/spanish.go @@ -0,0 +1,2071 @@ +package wordlists + +import ( + "fmt" + "hash/crc32" + "strings" +) + +func init() { + // Ensure word list is correct + // $ wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/spanish.txt + // $ crc32 spanish.txt + // 266e4f3d + checksum := crc32.ChecksumIEEE([]byte(spanish)) + if fmt.Sprintf("%x", checksum) != "266e4f3d" { + panic("spanish checksum invalid") + } +} + +// Spanish is a slice of mnemonic words taken from the bip39 specification +// https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/spanish.txt +var Spanish = strings.Split(strings.TrimSpace(spanish), "\n") +var spanish = `ábaco +abdomen +abeja +abierto +abogado +abono +aborto +abrazo +abrir +abuelo +abuso +acabar +academia +acceso +acción +aceite +acelga +acento +aceptar +ácido +aclarar +acné +acoger +acoso +activo +acto +actriz +actuar +acudir +acuerdo +acusar +adicto +admitir +adoptar +adorno +aduana +adulto +aéreo +afectar +afición +afinar +afirmar +ágil +agitar +agonía +agosto +agotar +agregar +agrio +agua +agudo +águila +aguja +ahogo +ahorro +aire +aislar +ajedrez +ajeno +ajuste +alacrán +alambre +alarma +alba +álbum +alcalde +aldea +alegre +alejar +alerta +aleta +alfiler +alga +algodón +aliado +aliento +alivio +alma +almeja +almíbar +altar +alteza +altivo +alto +altura +alumno +alzar +amable +amante +amapola +amargo +amasar +ámbar +ámbito +ameno +amigo +amistad +amor +amparo +amplio +ancho +anciano +ancla +andar +andén +anemia +ángulo +anillo +ánimo +anís +anotar +antena +antiguo +antojo +anual +anular +anuncio +añadir +añejo +año +apagar +aparato +apetito +apio +aplicar +apodo +aporte +apoyo +aprender +aprobar +apuesta +apuro +arado +araña +arar +árbitro +árbol +arbusto +archivo +arco +arder +ardilla +arduo +área +árido +aries +armonía +arnés +aroma +arpa +arpón +arreglo +arroz +arruga +arte +artista +asa +asado +asalto +ascenso +asegurar +aseo +asesor +asiento +asilo +asistir +asno +asombro +áspero +astilla +astro +astuto +asumir +asunto +atajo +ataque +atar +atento +ateo +ático +atleta +átomo +atraer +atroz +atún +audaz +audio +auge +aula +aumento +ausente +autor +aval +avance +avaro +ave +avellana +avena +avestruz +avión +aviso +ayer +ayuda +ayuno +azafrán +azar +azote +azúcar +azufre +azul +baba +babor +bache +bahía +baile +bajar +balanza +balcón +balde +bambú +banco +banda +baño +barba +barco +barniz +barro +báscula +bastón +basura +batalla +batería +batir +batuta +baúl +bazar +bebé +bebida +bello +besar +beso +bestia +bicho +bien +bingo +blanco +bloque +blusa +boa +bobina +bobo +boca +bocina +boda +bodega +boina +bola +bolero +bolsa +bomba +bondad +bonito +bono +bonsái +borde +borrar +bosque +bote +botín +bóveda +bozal +bravo +brazo +brecha +breve +brillo +brinco +brisa +broca +broma +bronce +brote +bruja +brusco +bruto +buceo +bucle +bueno +buey +bufanda +bufón +búho +buitre +bulto +burbuja +burla +burro +buscar +butaca +buzón +caballo +cabeza +cabina +cabra +cacao +cadáver +cadena +caer +café +caída +caimán +caja +cajón +cal +calamar +calcio +caldo +calidad +calle +calma +calor +calvo +cama +cambio +camello +camino +campo +cáncer +candil +canela +canguro +canica +canto +caña +cañón +caoba +caos +capaz +capitán +capote +captar +capucha +cara +carbón +cárcel +careta +carga +cariño +carne +carpeta +carro +carta +casa +casco +casero +caspa +castor +catorce +catre +caudal +causa +cazo +cebolla +ceder +cedro +celda +célebre +celoso +célula +cemento +ceniza +centro +cerca +cerdo +cereza +cero +cerrar +certeza +césped +cetro +chacal +chaleco +champú +chancla +chapa +charla +chico +chiste +chivo +choque +choza +chuleta +chupar +ciclón +ciego +cielo +cien +cierto +cifra +cigarro +cima +cinco +cine +cinta +ciprés +circo +ciruela +cisne +cita +ciudad +clamor +clan +claro +clase +clave +cliente +clima +clínica +cobre +cocción +cochino +cocina +coco +código +codo +cofre +coger +cohete +cojín +cojo +cola +colcha +colegio +colgar +colina +collar +colmo +columna +combate +comer +comida +cómodo +compra +conde +conejo +conga +conocer +consejo +contar +copa +copia +corazón +corbata +corcho +cordón +corona +correr +coser +cosmos +costa +cráneo +cráter +crear +crecer +creído +crema +cría +crimen +cripta +crisis +cromo +crónica +croqueta +crudo +cruz +cuadro +cuarto +cuatro +cubo +cubrir +cuchara +cuello +cuento +cuerda +cuesta +cueva +cuidar +culebra +culpa +culto +cumbre +cumplir +cuna +cuneta +cuota +cupón +cúpula +curar +curioso +curso +curva +cutis +dama +danza +dar +dardo +dátil +deber +débil +década +decir +dedo +defensa +definir +dejar +delfín +delgado +delito +demora +denso +dental +deporte +derecho +derrota +desayuno +deseo +desfile +desnudo +destino +desvío +detalle +detener +deuda +día +diablo +diadema +diamante +diana +diario +dibujo +dictar +diente +dieta +diez +difícil +digno +dilema +diluir +dinero +directo +dirigir +disco +diseño +disfraz +diva +divino +doble +doce +dolor +domingo +don +donar +dorado +dormir +dorso +dos +dosis +dragón +droga +ducha +duda +duelo +dueño +dulce +dúo +duque +durar +dureza +duro +ébano +ebrio +echar +eco +ecuador +edad +edición +edificio +editor +educar +efecto +eficaz +eje +ejemplo +elefante +elegir +elemento +elevar +elipse +élite +elixir +elogio +eludir +embudo +emitir +emoción +empate +empeño +empleo +empresa +enano +encargo +enchufe +encía +enemigo +enero +enfado +enfermo +engaño +enigma +enlace +enorme +enredo +ensayo +enseñar +entero +entrar +envase +envío +época +equipo +erizo +escala +escena +escolar +escribir +escudo +esencia +esfera +esfuerzo +espada +espejo +espía +esposa +espuma +esquí +estar +este +estilo +estufa +etapa +eterno +ética +etnia +evadir +evaluar +evento +evitar +exacto +examen +exceso +excusa +exento +exigir +exilio +existir +éxito +experto +explicar +exponer +extremo +fábrica +fábula +fachada +fácil +factor +faena +faja +falda +fallo +falso +faltar +fama +familia +famoso +faraón +farmacia +farol +farsa +fase +fatiga +fauna +favor +fax +febrero +fecha +feliz +feo +feria +feroz +fértil +fervor +festín +fiable +fianza +fiar +fibra +ficción +ficha +fideo +fiebre +fiel +fiera +fiesta +figura +fijar +fijo +fila +filete +filial +filtro +fin +finca +fingir +finito +firma +flaco +flauta +flecha +flor +flota +fluir +flujo +flúor +fobia +foca +fogata +fogón +folio +folleto +fondo +forma +forro +fortuna +forzar +fosa +foto +fracaso +frágil +franja +frase +fraude +freír +freno +fresa +frío +frito +fruta +fuego +fuente +fuerza +fuga +fumar +función +funda +furgón +furia +fusil +fútbol +futuro +gacela +gafas +gaita +gajo +gala +galería +gallo +gamba +ganar +gancho +ganga +ganso +garaje +garza +gasolina +gastar +gato +gavilán +gemelo +gemir +gen +género +genio +gente +geranio +gerente +germen +gesto +gigante +gimnasio +girar +giro +glaciar +globo +gloria +gol +golfo +goloso +golpe +goma +gordo +gorila +gorra +gota +goteo +gozar +grada +gráfico +grano +grasa +gratis +grave +grieta +grillo +gripe +gris +grito +grosor +grúa +grueso +grumo +grupo +guante +guapo +guardia +guerra +guía +guiño +guion +guiso +guitarra +gusano +gustar +haber +hábil +hablar +hacer +hacha +hada +hallar +hamaca +harina +haz +hazaña +hebilla +hebra +hecho +helado +helio +hembra +herir +hermano +héroe +hervir +hielo +hierro +hígado +higiene +hijo +himno +historia +hocico +hogar +hoguera +hoja +hombre +hongo +honor +honra +hora +hormiga +horno +hostil +hoyo +hueco +huelga +huerta +hueso +huevo +huida +huir +humano +húmedo +humilde +humo +hundir +huracán +hurto +icono +ideal +idioma +ídolo +iglesia +iglú +igual +ilegal +ilusión +imagen +imán +imitar +impar +imperio +imponer +impulso +incapaz +índice +inerte +infiel +informe +ingenio +inicio +inmenso +inmune +innato +insecto +instante +interés +íntimo +intuir +inútil +invierno +ira +iris +ironía +isla +islote +jabalí +jabón +jamón +jarabe +jardín +jarra +jaula +jazmín +jefe +jeringa +jinete +jornada +joroba +joven +joya +juerga +jueves +juez +jugador +jugo +juguete +juicio +junco +jungla +junio +juntar +júpiter +jurar +justo +juvenil +juzgar +kilo +koala +labio +lacio +lacra +lado +ladrón +lagarto +lágrima +laguna +laico +lamer +lámina +lámpara +lana +lancha +langosta +lanza +lápiz +largo +larva +lástima +lata +látex +latir +laurel +lavar +lazo +leal +lección +leche +lector +leer +legión +legumbre +lejano +lengua +lento +leña +león +leopardo +lesión +letal +letra +leve +leyenda +libertad +libro +licor +líder +lidiar +lienzo +liga +ligero +lima +límite +limón +limpio +lince +lindo +línea +lingote +lino +linterna +líquido +liso +lista +litera +litio +litro +llaga +llama +llanto +llave +llegar +llenar +llevar +llorar +llover +lluvia +lobo +loción +loco +locura +lógica +logro +lombriz +lomo +lonja +lote +lucha +lucir +lugar +lujo +luna +lunes +lupa +lustro +luto +luz +maceta +macho +madera +madre +maduro +maestro +mafia +magia +mago +maíz +maldad +maleta +malla +malo +mamá +mambo +mamut +manco +mando +manejar +manga +maniquí +manjar +mano +manso +manta +mañana +mapa +máquina +mar +marco +marea +marfil +margen +marido +mármol +marrón +martes +marzo +masa +máscara +masivo +matar +materia +matiz +matriz +máximo +mayor +mazorca +mecha +medalla +medio +médula +mejilla +mejor +melena +melón +memoria +menor +mensaje +mente +menú +mercado +merengue +mérito +mes +mesón +meta +meter +método +metro +mezcla +miedo +miel +miembro +miga +mil +milagro +militar +millón +mimo +mina +minero +mínimo +minuto +miope +mirar +misa +miseria +misil +mismo +mitad +mito +mochila +moción +moda +modelo +moho +mojar +molde +moler +molino +momento +momia +monarca +moneda +monja +monto +moño +morada +morder +moreno +morir +morro +morsa +mortal +mosca +mostrar +motivo +mover +móvil +mozo +mucho +mudar +mueble +muela +muerte +muestra +mugre +mujer +mula +muleta +multa +mundo +muñeca +mural +muro +músculo +museo +musgo +música +muslo +nácar +nación +nadar +naipe +naranja +nariz +narrar +nasal +natal +nativo +natural +náusea +naval +nave +navidad +necio +néctar +negar +negocio +negro +neón +nervio +neto +neutro +nevar +nevera +nicho +nido +niebla +nieto +niñez +niño +nítido +nivel +nobleza +noche +nómina +noria +norma +norte +nota +noticia +novato +novela +novio +nube +nuca +núcleo +nudillo +nudo +nuera +nueve +nuez +nulo +número +nutria +oasis +obeso +obispo +objeto +obra +obrero +observar +obtener +obvio +oca +ocaso +océano +ochenta +ocho +ocio +ocre +octavo +octubre +oculto +ocupar +ocurrir +odiar +odio +odisea +oeste +ofensa +oferta +oficio +ofrecer +ogro +oído +oír +ojo +ola +oleada +olfato +olivo +olla +olmo +olor +olvido +ombligo +onda +onza +opaco +opción +ópera +opinar +oponer +optar +óptica +opuesto +oración +orador +oral +órbita +orca +orden +oreja +órgano +orgía +orgullo +oriente +origen +orilla +oro +orquesta +oruga +osadía +oscuro +osezno +oso +ostra +otoño +otro +oveja +óvulo +óxido +oxígeno +oyente +ozono +pacto +padre +paella +página +pago +país +pájaro +palabra +palco +paleta +pálido +palma +paloma +palpar +pan +panal +pánico +pantera +pañuelo +papá +papel +papilla +paquete +parar +parcela +pared +parir +paro +párpado +parque +párrafo +parte +pasar +paseo +pasión +paso +pasta +pata +patio +patria +pausa +pauta +pavo +payaso +peatón +pecado +pecera +pecho +pedal +pedir +pegar +peine +pelar +peldaño +pelea +peligro +pellejo +pelo +peluca +pena +pensar +peñón +peón +peor +pepino +pequeño +pera +percha +perder +pereza +perfil +perico +perla +permiso +perro +persona +pesa +pesca +pésimo +pestaña +pétalo +petróleo +pez +pezuña +picar +pichón +pie +piedra +pierna +pieza +pijama +pilar +piloto +pimienta +pino +pintor +pinza +piña +piojo +pipa +pirata +pisar +piscina +piso +pista +pitón +pizca +placa +plan +plata +playa +plaza +pleito +pleno +plomo +pluma +plural +pobre +poco +poder +podio +poema +poesía +poeta +polen +policía +pollo +polvo +pomada +pomelo +pomo +pompa +poner +porción +portal +posada +poseer +posible +poste +potencia +potro +pozo +prado +precoz +pregunta +premio +prensa +preso +previo +primo +príncipe +prisión +privar +proa +probar +proceso +producto +proeza +profesor +programa +prole +promesa +pronto +propio +próximo +prueba +público +puchero +pudor +pueblo +puerta +puesto +pulga +pulir +pulmón +pulpo +pulso +puma +punto +puñal +puño +pupa +pupila +puré +quedar +queja +quemar +querer +queso +quieto +química +quince +quitar +rábano +rabia +rabo +ración +radical +raíz +rama +rampa +rancho +rango +rapaz +rápido +rapto +rasgo +raspa +rato +rayo +raza +razón +reacción +realidad +rebaño +rebote +recaer +receta +rechazo +recoger +recreo +recto +recurso +red +redondo +reducir +reflejo +reforma +refrán +refugio +regalo +regir +regla +regreso +rehén +reino +reír +reja +relato +relevo +relieve +relleno +reloj +remar +remedio +remo +rencor +rendir +renta +reparto +repetir +reposo +reptil +res +rescate +resina +respeto +resto +resumen +retiro +retorno +retrato +reunir +revés +revista +rey +rezar +rico +riego +rienda +riesgo +rifa +rígido +rigor +rincón +riñón +río +riqueza +risa +ritmo +rito +rizo +roble +roce +rociar +rodar +rodeo +rodilla +roer +rojizo +rojo +romero +romper +ron +ronco +ronda +ropa +ropero +rosa +rosca +rostro +rotar +rubí +rubor +rudo +rueda +rugir +ruido +ruina +ruleta +rulo +rumbo +rumor +ruptura +ruta +rutina +sábado +saber +sabio +sable +sacar +sagaz +sagrado +sala +saldo +salero +salir +salmón +salón +salsa +salto +salud +salvar +samba +sanción +sandía +sanear +sangre +sanidad +sano +santo +sapo +saque +sardina +sartén +sastre +satán +sauna +saxofón +sección +seco +secreto +secta +sed +seguir +seis +sello +selva +semana +semilla +senda +sensor +señal +señor +separar +sepia +sequía +ser +serie +sermón +servir +sesenta +sesión +seta +setenta +severo +sexo +sexto +sidra +siesta +siete +siglo +signo +sílaba +silbar +silencio +silla +símbolo +simio +sirena +sistema +sitio +situar +sobre +socio +sodio +sol +solapa +soldado +soledad +sólido +soltar +solución +sombra +sondeo +sonido +sonoro +sonrisa +sopa +soplar +soporte +sordo +sorpresa +sorteo +sostén +sótano +suave +subir +suceso +sudor +suegra +suelo +sueño +suerte +sufrir +sujeto +sultán +sumar +superar +suplir +suponer +supremo +sur +surco +sureño +surgir +susto +sutil +tabaco +tabique +tabla +tabú +taco +tacto +tajo +talar +talco +talento +talla +talón +tamaño +tambor +tango +tanque +tapa +tapete +tapia +tapón +taquilla +tarde +tarea +tarifa +tarjeta +tarot +tarro +tarta +tatuaje +tauro +taza +tazón +teatro +techo +tecla +técnica +tejado +tejer +tejido +tela +teléfono +tema +temor +templo +tenaz +tender +tener +tenis +tenso +teoría +terapia +terco +término +ternura +terror +tesis +tesoro +testigo +tetera +texto +tez +tibio +tiburón +tiempo +tienda +tierra +tieso +tigre +tijera +tilde +timbre +tímido +timo +tinta +tío +típico +tipo +tira +tirón +titán +títere +título +tiza +toalla +tobillo +tocar +tocino +todo +toga +toldo +tomar +tono +tonto +topar +tope +toque +tórax +torero +tormenta +torneo +toro +torpedo +torre +torso +tortuga +tos +tosco +toser +tóxico +trabajo +tractor +traer +tráfico +trago +traje +tramo +trance +trato +trauma +trazar +trébol +tregua +treinta +tren +trepar +tres +tribu +trigo +tripa +triste +triunfo +trofeo +trompa +tronco +tropa +trote +trozo +truco +trueno +trufa +tubería +tubo +tuerto +tumba +tumor +túnel +túnica +turbina +turismo +turno +tutor +ubicar +úlcera +umbral +unidad +unir +universo +uno +untar +uña +urbano +urbe +urgente +urna +usar +usuario +útil +utopía +uva +vaca +vacío +vacuna +vagar +vago +vaina +vajilla +vale +válido +valle +valor +válvula +vampiro +vara +variar +varón +vaso +vecino +vector +vehículo +veinte +vejez +vela +velero +veloz +vena +vencer +venda +veneno +vengar +venir +venta +venus +ver +verano +verbo +verde +vereda +verja +verso +verter +vía +viaje +vibrar +vicio +víctima +vida +vídeo +vidrio +viejo +viernes +vigor +vil +villa +vinagre +vino +viñedo +violín +viral +virgo +virtud +visor +víspera +vista +vitamina +viudo +vivaz +vivero +vivir +vivo +volcán +volumen +volver +voraz +votar +voto +voz +vuelo +vulgar +yacer +yate +yegua +yema +yerno +yeso +yodo +yoga +yogur +zafiro +zanja +zapato +zarza +zona +zorro +zumo +zurdo +` diff --git a/vendor/github.com/wsddn/go-ecdh/.gitignore b/vendor/github.com/wsddn/go-ecdh/.gitignore new file mode 100644 index 000000000..8d87f6f3b --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test + +.directory diff --git a/vendor/github.com/wsddn/go-ecdh/.travis.yml b/vendor/github.com/wsddn/go-ecdh/.travis.yml new file mode 100644 index 000000000..0ebc231f8 --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - 1.2 + - tip + +install: go get golang.org/x/crypto/curve25519 + +script: +- go get github.com/tang0th/go-ecdh +- go test github.com/tang0th/go-ecdh diff --git a/vendor/github.com/wsddn/go-ecdh/LICENSE b/vendor/github.com/wsddn/go-ecdh/LICENSE new file mode 100644 index 000000000..c16b0acf7 --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2014, tang0th +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of tang0th nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/wsddn/go-ecdh/Readme.md b/vendor/github.com/wsddn/go-ecdh/Readme.md new file mode 100644 index 000000000..1445f68b1 --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/Readme.md @@ -0,0 +1,19 @@ +# ECDH + +[![Build Status](https://travis-ci.org/wsddn/go-ecdh.svg?branch=master)](https://travis-ci.org/wsddn/go-ecdh) + +This is a go implementation of elliptical curve diffie-hellman key exchange method. +It supports the NIST curves (and any curves using the `elliptic.Curve` go interface) +as well as djb's curve25519. + +The library handles generating of keys, generating a shared secret, and the +(un)marshalling of the elliptical curve keys into slices of bytes. + +## Warning and Disclaimer +I am not a cryptographer, this was written as part of a personal project to learn about cryptographic systems and protocols. No claims as to the security of this library are made, I would not advise using it for anything that requires any level of security. Pull requests or issues about security flaws are however still welcome. + +## Compatibility +Works with go 1.2 onwards. + +## TODO + * Improve documentation diff --git a/vendor/github.com/wsddn/go-ecdh/curve25519.go b/vendor/github.com/wsddn/go-ecdh/curve25519.go new file mode 100644 index 000000000..6426cbf8a --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/curve25519.go @@ -0,0 +1,62 @@ +package ecdh + +import ( + "crypto" + "io" + + "golang.org/x/crypto/curve25519" +) + +type curve25519ECDH struct { + ECDH +} + +// NewCurve25519ECDH creates a new ECDH instance that uses djb's curve25519 +// elliptical curve. +func NewCurve25519ECDH() ECDH { + return &curve25519ECDH{} +} + +func (e *curve25519ECDH) GenerateKey(rand io.Reader) (crypto.PrivateKey, crypto.PublicKey, error) { + var pub, priv [32]byte + var err error + + _, err = io.ReadFull(rand, priv[:]) + if err != nil { + return nil, nil, err + } + + priv[0] &= 248 + priv[31] &= 127 + priv[31] |= 64 + + curve25519.ScalarBaseMult(&pub, &priv) + + return &priv, &pub, nil +} + +func (e *curve25519ECDH) Marshal(p crypto.PublicKey) []byte { + pub := p.(*[32]byte) + return pub[:] +} + +func (e *curve25519ECDH) Unmarshal(data []byte) (crypto.PublicKey, bool) { + var pub [32]byte + if len(data) != 32 { + return nil, false + } + + copy(pub[:], data) + return &pub, true +} + +func (e *curve25519ECDH) GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ([]byte, error) { + var priv, pub, secret *[32]byte + + priv = privKey.(*[32]byte) + pub = pubKey.(*[32]byte) + secret = new([32]byte) + + curve25519.ScalarMult(secret, priv, pub) + return secret[:], nil +} diff --git a/vendor/github.com/wsddn/go-ecdh/ecdh.go b/vendor/github.com/wsddn/go-ecdh/ecdh.go new file mode 100644 index 000000000..921754fdc --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/ecdh.go @@ -0,0 +1,14 @@ +package ecdh + +import ( + "crypto" + "io" +) + +// The main interface for ECDH key exchange. +type ECDH interface { + GenerateKey(io.Reader) (crypto.PrivateKey, crypto.PublicKey, error) + Marshal(crypto.PublicKey) []byte + Unmarshal([]byte) (crypto.PublicKey, bool) + GenerateSharedSecret(crypto.PrivateKey, crypto.PublicKey) ([]byte, error) +} diff --git a/vendor/github.com/wsddn/go-ecdh/elliptic.go b/vendor/github.com/wsddn/go-ecdh/elliptic.go new file mode 100644 index 000000000..502563c40 --- /dev/null +++ b/vendor/github.com/wsddn/go-ecdh/elliptic.go @@ -0,0 +1,87 @@ +package ecdh + +import ( + "crypto" + "crypto/elliptic" + "io" + "math/big" +) + +type ellipticECDH struct { + ECDH + curve elliptic.Curve +} + +type ellipticPublicKey struct { + elliptic.Curve + X, Y *big.Int +} + +type ellipticPrivateKey struct { + D []byte +} + +// NewEllipticECDH creates a new instance of ECDH with the given elliptic.Curve curve +// to use as the elliptical curve for elliptical curve diffie-hellman. +func NewEllipticECDH(curve elliptic.Curve) ECDH { + return &ellipticECDH{ + curve: curve, + } +} + +func (e *ellipticECDH) GenerateKey(rand io.Reader) (crypto.PrivateKey, crypto.PublicKey, error) { + var d []byte + var x, y *big.Int + var priv *ellipticPrivateKey + var pub *ellipticPublicKey + var err error + + d, x, y, err = elliptic.GenerateKey(e.curve, rand) + if err != nil { + return nil, nil, err + } + + priv = &ellipticPrivateKey{ + D: d, + } + pub = &ellipticPublicKey{ + Curve: e.curve, + X: x, + Y: y, + } + + return priv, pub, nil +} + +func (e *ellipticECDH) Marshal(p crypto.PublicKey) []byte { + pub := p.(*ellipticPublicKey) + return elliptic.Marshal(e.curve, pub.X, pub.Y) +} + +func (e *ellipticECDH) Unmarshal(data []byte) (crypto.PublicKey, bool) { + var key *ellipticPublicKey + var x, y *big.Int + + x, y = elliptic.Unmarshal(e.curve, data) + if x == nil || y == nil { + return key, false + } + key = &ellipticPublicKey{ + Curve: e.curve, + X: x, + Y: y, + } + return key, true +} + +// GenerateSharedSecret takes in a public key and a private key +// and generates a shared secret. +// +// RFC5903 Section 9 states we should only return x. +func (e *ellipticECDH) GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ([]byte, error) { + priv := privKey.(*ellipticPrivateKey) + pub := pubKey.(*ellipticPublicKey) + + x, _ := e.curve.ScalarMult(pub.X, pub.Y, priv.D) + return x.Bytes(), nil +} diff --git a/vendor/go.opencensus.io/AUTHORS b/vendor/go.opencensus.io/AUTHORS new file mode 100644 index 000000000..e491a9e7f --- /dev/null +++ b/vendor/go.opencensus.io/AUTHORS @@ -0,0 +1 @@ +Google Inc. diff --git a/vendor/go.opencensus.io/LICENSE b/vendor/go.opencensus.io/LICENSE new file mode 100644 index 000000000..7a4a3ea24 --- /dev/null +++ b/vendor/go.opencensus.io/LICENSE @@ -0,0 +1,202 @@ + + 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. \ No newline at end of file diff --git a/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go new file mode 100644 index 000000000..41b2c3fc0 --- /dev/null +++ b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go @@ -0,0 +1,75 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +// Package tagencoding contains the tag encoding +// used interally by the stats collector. +package tagencoding // import "go.opencensus.io/internal/tagencoding" + +// Values represent the encoded buffer for the values. +type Values struct { + Buffer []byte + WriteIndex int + ReadIndex int +} + +func (vb *Values) growIfRequired(expected int) { + if len(vb.Buffer)-vb.WriteIndex < expected { + tmp := make([]byte, 2*(len(vb.Buffer)+1)+expected) + copy(tmp, vb.Buffer) + vb.Buffer = tmp + } +} + +// WriteValue is the helper method to encode Values from map[Key][]byte. +func (vb *Values) WriteValue(v []byte) { + length := len(v) & 0xff + vb.growIfRequired(1 + length) + + // writing length of v + vb.Buffer[vb.WriteIndex] = byte(length) + vb.WriteIndex++ + + if length == 0 { + // No value was encoded for this key + return + } + + // writing v + copy(vb.Buffer[vb.WriteIndex:], v[:length]) + vb.WriteIndex += length +} + +// ReadValue is the helper method to decode Values to a map[Key][]byte. +func (vb *Values) ReadValue() []byte { + // read length of v + length := int(vb.Buffer[vb.ReadIndex]) + vb.ReadIndex++ + if length == 0 { + // No value was encoded for this key + return nil + } + + // read value of v + v := make([]byte, length) + endIdx := vb.ReadIndex + length + copy(v, vb.Buffer[vb.ReadIndex:endIdx]) + vb.ReadIndex = endIdx + return v +} + +// Bytes returns a reference to already written bytes in the Buffer. +func (vb *Values) Bytes() []byte { + return vb.Buffer[:vb.WriteIndex] +} diff --git a/vendor/go.opencensus.io/metric/metricdata/doc.go b/vendor/go.opencensus.io/metric/metricdata/doc.go new file mode 100644 index 000000000..52a7b3bf8 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/doc.go @@ -0,0 +1,19 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +// Package metricdata contains the metrics data model. +// +// This is an EXPERIMENTAL package, and may change in arbitrary ways without +// notice. +package metricdata // import "go.opencensus.io/metric/metricdata" diff --git a/vendor/go.opencensus.io/metric/metricdata/exemplar.go b/vendor/go.opencensus.io/metric/metricdata/exemplar.go new file mode 100644 index 000000000..12695ce2d --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/exemplar.go @@ -0,0 +1,38 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package metricdata + +import ( + "time" +) + +// Exemplars keys. +const ( + AttachmentKeySpanContext = "SpanContext" +) + +// Exemplar is an example data point associated with each bucket of a +// distribution type aggregation. +// +// Their purpose is to provide an example of the kind of thing +// (request, RPC, trace span, etc.) that resulted in that measurement. +type Exemplar struct { + Value float64 // the value that was recorded + Timestamp time.Time // the time the value was recorded + Attachments Attachments // attachments (if any) +} + +// Attachments is a map of extra values associated with a recorded data point. +type Attachments map[string]interface{} diff --git a/vendor/go.opencensus.io/metric/metricdata/label.go b/vendor/go.opencensus.io/metric/metricdata/label.go new file mode 100644 index 000000000..aadae41e6 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/label.go @@ -0,0 +1,35 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package metricdata + +// LabelKey represents key of a label. It has optional +// description attribute. +type LabelKey struct { + Key string + Description string +} + +// LabelValue represents the value of a label. +// The zero value represents a missing label value, which may be treated +// differently to an empty string value by some back ends. +type LabelValue struct { + Value string // string value of the label + Present bool // flag that indicated whether a value is present or not +} + +// NewLabelValue creates a new non-nil LabelValue that represents the given string. +func NewLabelValue(val string) LabelValue { + return LabelValue{Value: val, Present: true} +} diff --git a/vendor/go.opencensus.io/metric/metricdata/metric.go b/vendor/go.opencensus.io/metric/metricdata/metric.go new file mode 100644 index 000000000..8293712c7 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/metric.go @@ -0,0 +1,46 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package metricdata + +import ( + "time" + + "go.opencensus.io/resource" +) + +// Descriptor holds metadata about a metric. +type Descriptor struct { + Name string // full name of the metric + Description string // human-readable description + Unit Unit // units for the measure + Type Type // type of measure + LabelKeys []LabelKey // label keys +} + +// Metric represents a quantity measured against a resource with different +// label value combinations. +type Metric struct { + Descriptor Descriptor // metric descriptor + Resource *resource.Resource // resource against which this was measured + TimeSeries []*TimeSeries // one time series for each combination of label values +} + +// TimeSeries is a sequence of points associated with a combination of label +// values. +type TimeSeries struct { + LabelValues []LabelValue // label values, same order as keys in the metric descriptor + Points []Point // points sequence + StartTime time.Time // time we started recording this time series +} diff --git a/vendor/go.opencensus.io/metric/metricdata/point.go b/vendor/go.opencensus.io/metric/metricdata/point.go new file mode 100644 index 000000000..7fe057b19 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/point.go @@ -0,0 +1,193 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package metricdata + +import ( + "time" +) + +// Point is a single data point of a time series. +type Point struct { + // Time is the point in time that this point represents in a time series. + Time time.Time + // Value is the value of this point. Prefer using ReadValue to switching on + // the value type, since new value types might be added. + Value interface{} +} + +//go:generate stringer -type ValueType + +// NewFloat64Point creates a new Point holding a float64 value. +func NewFloat64Point(t time.Time, val float64) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewInt64Point creates a new Point holding an int64 value. +func NewInt64Point(t time.Time, val int64) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewDistributionPoint creates a new Point holding a Distribution value. +func NewDistributionPoint(t time.Time, val *Distribution) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewSummaryPoint creates a new Point holding a Summary value. +func NewSummaryPoint(t time.Time, val *Summary) Point { + return Point{ + Value: val, + Time: t, + } +} + +// ValueVisitor allows reading the value of a point. +type ValueVisitor interface { + VisitFloat64Value(float64) + VisitInt64Value(int64) + VisitDistributionValue(*Distribution) + VisitSummaryValue(*Summary) +} + +// ReadValue accepts a ValueVisitor and calls the appropriate method with the +// value of this point. +// Consumers of Point should use this in preference to switching on the type +// of the value directly, since new value types may be added. +func (p Point) ReadValue(vv ValueVisitor) { + switch v := p.Value.(type) { + case int64: + vv.VisitInt64Value(v) + case float64: + vv.VisitFloat64Value(v) + case *Distribution: + vv.VisitDistributionValue(v) + case *Summary: + vv.VisitSummaryValue(v) + default: + panic("unexpected value type") + } +} + +// Distribution contains summary statistics for a population of values. It +// optionally contains a histogram representing the distribution of those +// values across a set of buckets. +type Distribution struct { + // Count is the number of values in the population. Must be non-negative. This value + // must equal the sum of the values in bucket_counts if a histogram is + // provided. + Count int64 + // Sum is the sum of the values in the population. If count is zero then this field + // must be zero. + Sum float64 + // SumOfSquaredDeviation is the sum of squared deviations from the mean of the values in the + // population. For values x_i this is: + // + // Sum[i=1..n]((x_i - mean)^2) + // + // Knuth, "The Art of Computer Programming", Vol. 2, page 323, 3rd edition + // describes Welford's method for accumulating this sum in one pass. + // + // If count is zero then this field must be zero. + SumOfSquaredDeviation float64 + // BucketOptions describes the bounds of the histogram buckets in this + // distribution. + // + // A Distribution may optionally contain a histogram of the values in the + // population. + // + // If nil, there is no associated histogram. + BucketOptions *BucketOptions + // Bucket If the distribution does not have a histogram, then omit this field. + // If there is a histogram, then the sum of the values in the Bucket counts + // must equal the value in the count field of the distribution. + Buckets []Bucket +} + +// BucketOptions describes the bounds of the histogram buckets in this +// distribution. +type BucketOptions struct { + // Bounds specifies a set of bucket upper bounds. + // This defines len(bounds) + 1 (= N) buckets. The boundaries for bucket + // index i are: + // + // [0, Bounds[i]) for i == 0 + // [Bounds[i-1], Bounds[i]) for 0 < i < N-1 + // [Bounds[i-1], +infinity) for i == N-1 + Bounds []float64 +} + +// Bucket represents a single bucket (value range) in a distribution. +type Bucket struct { + // Count is the number of values in each bucket of the histogram, as described in + // bucket_bounds. + Count int64 + // Exemplar associated with this bucket (if any). + Exemplar *Exemplar +} + +// Summary is a representation of percentiles. +type Summary struct { + // Count is the cumulative count (if available). + Count int64 + // Sum is the cumulative sum of values (if available). + Sum float64 + // HasCountAndSum is true if Count and Sum are available. + HasCountAndSum bool + // Snapshot represents percentiles calculated over an arbitrary time window. + // The values in this struct can be reset at arbitrary unknown times, with + // the requirement that all of them are reset at the same time. + Snapshot Snapshot +} + +// Snapshot represents percentiles over an arbitrary time. +// The values in this struct can be reset at arbitrary unknown times, with +// the requirement that all of them are reset at the same time. +type Snapshot struct { + // Count is the number of values in the snapshot. Optional since some systems don't + // expose this. Set to 0 if not available. + Count int64 + // Sum is the sum of values in the snapshot. Optional since some systems don't + // expose this. If count is 0 then this field must be zero. + Sum float64 + // Percentiles is a map from percentile (range (0-100.0]) to the value of + // the percentile. + Percentiles map[float64]float64 +} + +//go:generate stringer -type Type + +// Type is the overall type of metric, including its value type and whether it +// represents a cumulative total (since the start time) or if it represents a +// gauge value. +type Type int + +// Metric types. +const ( + TypeGaugeInt64 Type = iota + TypeGaugeFloat64 + TypeGaugeDistribution + TypeCumulativeInt64 + TypeCumulativeFloat64 + TypeCumulativeDistribution + TypeSummary +) diff --git a/vendor/go.opencensus.io/metric/metricdata/type_string.go b/vendor/go.opencensus.io/metric/metricdata/type_string.go new file mode 100644 index 000000000..c3f8ec27b --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/type_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type Type"; DO NOT EDIT. + +package metricdata + +import "strconv" + +const _Type_name = "TypeGaugeInt64TypeGaugeFloat64TypeGaugeDistributionTypeCumulativeInt64TypeCumulativeFloat64TypeCumulativeDistributionTypeSummary" + +var _Type_index = [...]uint8{0, 14, 30, 51, 70, 91, 117, 128} + +func (i Type) String() string { + if i < 0 || i >= Type(len(_Type_index)-1) { + return "Type(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Type_name[_Type_index[i]:_Type_index[i+1]] +} diff --git a/vendor/go.opencensus.io/metric/metricdata/unit.go b/vendor/go.opencensus.io/metric/metricdata/unit.go new file mode 100644 index 000000000..b483a1371 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/unit.go @@ -0,0 +1,27 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package metricdata + +// Unit is a string encoded according to the case-sensitive abbreviations from the +// Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html +type Unit string + +// Predefined units. To record against a unit not represented here, create your +// own Unit type constant from a string. +const ( + UnitDimensionless Unit = "1" + UnitBytes Unit = "By" + UnitMilliseconds Unit = "ms" +) diff --git a/vendor/go.opencensus.io/metric/metricproducer/manager.go b/vendor/go.opencensus.io/metric/metricproducer/manager.go new file mode 100644 index 000000000..ca1f39049 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricproducer/manager.go @@ -0,0 +1,78 @@ +// Copyright 2019, OpenCensus Authors +// +// 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. + +package metricproducer + +import ( + "sync" +) + +// Manager maintains a list of active producers. Producers can register +// with the manager to allow readers to read all metrics provided by them. +// Readers can retrieve all producers registered with the manager, +// read metrics from the producers and export them. +type Manager struct { + mu sync.RWMutex + producers map[Producer]struct{} +} + +var prodMgr *Manager +var once sync.Once + +// GlobalManager is a single instance of producer manager +// that is used by all producers and all readers. +func GlobalManager() *Manager { + once.Do(func() { + prodMgr = &Manager{} + prodMgr.producers = make(map[Producer]struct{}) + }) + return prodMgr +} + +// AddProducer adds the producer to the Manager if it is not already present. +func (pm *Manager) AddProducer(producer Producer) { + if producer == nil { + return + } + pm.mu.Lock() + defer pm.mu.Unlock() + pm.producers[producer] = struct{}{} +} + +// DeleteProducer deletes the producer from the Manager if it is present. +func (pm *Manager) DeleteProducer(producer Producer) { + if producer == nil { + return + } + pm.mu.Lock() + defer pm.mu.Unlock() + delete(pm.producers, producer) +} + +// GetAll returns a slice of all producer currently registered with +// the Manager. For each call it generates a new slice. The slice +// should not be cached as registration may change at any time. It is +// typically called periodically by exporter to read metrics from +// the producers. +func (pm *Manager) GetAll() []Producer { + pm.mu.Lock() + defer pm.mu.Unlock() + producers := make([]Producer, len(pm.producers)) + i := 0 + for producer := range pm.producers { + producers[i] = producer + i++ + } + return producers +} diff --git a/vendor/go.opencensus.io/metric/metricproducer/producer.go b/vendor/go.opencensus.io/metric/metricproducer/producer.go new file mode 100644 index 000000000..6cee9ed17 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricproducer/producer.go @@ -0,0 +1,28 @@ +// Copyright 2019, OpenCensus Authors +// +// 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. + +package metricproducer + +import ( + "go.opencensus.io/metric/metricdata" +) + +// Producer is a source of metrics. +type Producer interface { + // Read should return the current values of all metrics supported by this + // metric provider. + // The returned metrics should be unique for each combination of name and + // resource. + Read() []*metricdata.Metric +} diff --git a/vendor/go.opencensus.io/resource/resource.go b/vendor/go.opencensus.io/resource/resource.go new file mode 100644 index 000000000..b1764e1d3 --- /dev/null +++ b/vendor/go.opencensus.io/resource/resource.go @@ -0,0 +1,164 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +// Package resource provides functionality for resource, which capture +// identifying information about the entities for which signals are exported. +package resource + +import ( + "context" + "fmt" + "os" + "regexp" + "sort" + "strconv" + "strings" +) + +// Environment variables used by FromEnv to decode a resource. +const ( + EnvVarType = "OC_RESOURCE_TYPE" + EnvVarLabels = "OC_RESOURCE_LABELS" +) + +// Resource describes an entity about which identifying information and metadata is exposed. +// For example, a type "k8s.io/container" may hold labels describing the pod name and namespace. +type Resource struct { + Type string + Labels map[string]string +} + +// EncodeLabels encodes a labels map to a string as provided via the OC_RESOURCE_LABELS environment variable. +func EncodeLabels(labels map[string]string) string { + sortedKeys := make([]string, 0, len(labels)) + for k := range labels { + sortedKeys = append(sortedKeys, k) + } + sort.Strings(sortedKeys) + + s := "" + for i, k := range sortedKeys { + if i > 0 { + s += "," + } + s += k + "=" + strconv.Quote(labels[k]) + } + return s +} + +var labelRegex = regexp.MustCompile(`^\s*([[:ascii:]]{1,256}?)=("[[:ascii:]]{0,256}?")\s*,`) + +// DecodeLabels decodes a serialized label map as used in the OC_RESOURCE_LABELS variable. +// A list of labels of the form `="",="",...` is accepted. +// Domain names and paths are accepted as label keys. +// Most users will want to use FromEnv instead. +func DecodeLabels(s string) (map[string]string, error) { + m := map[string]string{} + // Ensure a trailing comma, which allows us to keep the regex simpler + s = strings.TrimRight(strings.TrimSpace(s), ",") + "," + + for len(s) > 0 { + match := labelRegex.FindStringSubmatch(s) + if len(match) == 0 { + return nil, fmt.Errorf("invalid label formatting, remainder: %s", s) + } + v := match[2] + if v == "" { + v = match[3] + } else { + var err error + if v, err = strconv.Unquote(v); err != nil { + return nil, fmt.Errorf("invalid label formatting, remainder: %s, err: %s", s, err) + } + } + m[match[1]] = v + + s = s[len(match[0]):] + } + return m, nil +} + +// FromEnv is a detector that loads resource information from the OC_RESOURCE_TYPE +// and OC_RESOURCE_labelS environment variables. +func FromEnv(context.Context) (*Resource, error) { + res := &Resource{ + Type: strings.TrimSpace(os.Getenv(EnvVarType)), + } + labels := strings.TrimSpace(os.Getenv(EnvVarLabels)) + if labels == "" { + return res, nil + } + var err error + if res.Labels, err = DecodeLabels(labels); err != nil { + return nil, err + } + return res, nil +} + +var _ Detector = FromEnv + +// merge resource information from b into a. In case of a collision, a takes precedence. +func merge(a, b *Resource) *Resource { + if a == nil { + return b + } + if b == nil { + return a + } + res := &Resource{ + Type: a.Type, + Labels: map[string]string{}, + } + if res.Type == "" { + res.Type = b.Type + } + for k, v := range b.Labels { + res.Labels[k] = v + } + // Labels from resource a overwrite labels from resource b. + for k, v := range a.Labels { + res.Labels[k] = v + } + return res +} + +// Detector attempts to detect resource information. +// If the detector cannot find resource information, the returned resource is nil but no +// error is returned. +// An error is only returned on unexpected failures. +type Detector func(context.Context) (*Resource, error) + +// MultiDetector returns a Detector that calls all input detectors in order and +// merges each result with the previous one. In case a type of label key is already set, +// the first set value is takes precedence. +// It returns on the first error that a sub-detector encounters. +func MultiDetector(detectors ...Detector) Detector { + return func(ctx context.Context) (*Resource, error) { + return detectAll(ctx, detectors...) + } +} + +// detectall calls all input detectors sequentially an merges each result with the previous one. +// It returns on the first error that a sub-detector encounters. +func detectAll(ctx context.Context, detectors ...Detector) (*Resource, error) { + var res *Resource + for _, d := range detectors { + r, err := d(ctx) + if err != nil { + return nil, err + } + res = merge(res, r) + } + return res, nil +} diff --git a/vendor/go.opencensus.io/stats/doc.go b/vendor/go.opencensus.io/stats/doc.go new file mode 100644 index 000000000..00d473ee0 --- /dev/null +++ b/vendor/go.opencensus.io/stats/doc.go @@ -0,0 +1,69 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +/* +Package stats contains support for OpenCensus stats recording. + +OpenCensus allows users to create typed measures, record measurements, +aggregate the collected data, and export the aggregated data. + +Measures + +A measure represents a type of data point to be tracked and recorded. +For example, latency, request Mb/s, and response Mb/s are measures +to collect from a server. + +Measure constructors such as Int64 and Float64 automatically +register the measure by the given name. Each registered measure needs +to be unique by name. Measures also have a description and a unit. + +Libraries can define and export measures. Application authors can then +create views and collect and break down measures by the tags they are +interested in. + +Recording measurements + +Measurement is a data point to be collected for a measure. For example, +for a latency (ms) measure, 100 is a measurement that represents a 100ms +latency event. Measurements are created from measures with +the current context. Tags from the current context are recorded with the +measurements if they are any. + +Recorded measurements are dropped immediately if no views are registered for them. +There is usually no need to conditionally enable and disable +recording to reduce cost. Recording of measurements is cheap. + +Libraries can always record measurements, and applications can later decide +on which measurements they want to collect by registering views. This allows +libraries to turn on the instrumentation by default. + +Exemplars + +For a given recorded measurement, the associated exemplar is a diagnostic map +that gives more information about the measurement. + +When aggregated using a Distribution aggregation, an exemplar is kept for each +bucket in the Distribution. This allows you to easily find an example of a +measurement that fell into each bucket. + +For example, if you also use the OpenCensus trace package and you +record a measurement with a context that contains a sampled trace span, +then the trace span will be added to the exemplar associated with the measurement. + +When exported to a supporting back end, you should be able to easily navigate +to example traces that fell into each bucket in the Distribution. + +*/ +package stats // import "go.opencensus.io/stats" diff --git a/vendor/go.opencensus.io/stats/internal/record.go b/vendor/go.opencensus.io/stats/internal/record.go new file mode 100644 index 000000000..36935e629 --- /dev/null +++ b/vendor/go.opencensus.io/stats/internal/record.go @@ -0,0 +1,25 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +package internal + +import ( + "go.opencensus.io/tag" +) + +// DefaultRecorder will be called for each Record call. +var DefaultRecorder func(tags *tag.Map, measurement interface{}, attachments map[string]interface{}) + +// SubscriptionReporter reports when a view subscribed with a measure. +var SubscriptionReporter func(measure string) diff --git a/vendor/go.opencensus.io/stats/measure.go b/vendor/go.opencensus.io/stats/measure.go new file mode 100644 index 000000000..1ffd3cefc --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure.go @@ -0,0 +1,109 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package stats + +import ( + "sync" + "sync/atomic" +) + +// Measure represents a single numeric value to be tracked and recorded. +// For example, latency, request bytes, and response bytes could be measures +// to collect from a server. +// +// Measures by themselves have no outside effects. In order to be exported, +// the measure needs to be used in a View. If no Views are defined over a +// measure, there is very little cost in recording it. +type Measure interface { + // Name returns the name of this measure. + // + // Measure names are globally unique (among all libraries linked into your program). + // We recommend prefixing the measure name with a domain name relevant to your + // project or application. + // + // Measure names are never sent over the wire or exported to backends. + // They are only used to create Views. + Name() string + + // Description returns the human-readable description of this measure. + Description() string + + // Unit returns the units for the values this measure takes on. + // + // Units are encoded according to the case-sensitive abbreviations from the + // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html + Unit() string +} + +// measureDescriptor is the untyped descriptor associated with each measure. +// Int64Measure and Float64Measure wrap measureDescriptor to provide typed +// recording APIs. +// Two Measures with the same name will have the same measureDescriptor. +type measureDescriptor struct { + subs int32 // access atomically + + name string + description string + unit string +} + +func (m *measureDescriptor) subscribe() { + atomic.StoreInt32(&m.subs, 1) +} + +func (m *measureDescriptor) subscribed() bool { + return atomic.LoadInt32(&m.subs) == 1 +} + +var ( + mu sync.RWMutex + measures = make(map[string]*measureDescriptor) +) + +func registerMeasureHandle(name, desc, unit string) *measureDescriptor { + mu.Lock() + defer mu.Unlock() + + if stored, ok := measures[name]; ok { + return stored + } + m := &measureDescriptor{ + name: name, + description: desc, + unit: unit, + } + measures[name] = m + return m +} + +// Measurement is the numeric value measured when recording stats. Each measure +// provides methods to create measurements of their kind. For example, Int64Measure +// provides M to convert an int64 into a measurement. +type Measurement struct { + v float64 + m Measure + desc *measureDescriptor +} + +// Value returns the value of the Measurement as a float64. +func (m Measurement) Value() float64 { + return m.v +} + +// Measure returns the Measure from which this Measurement was created. +func (m Measurement) Measure() Measure { + return m.m +} diff --git a/vendor/go.opencensus.io/stats/measure_float64.go b/vendor/go.opencensus.io/stats/measure_float64.go new file mode 100644 index 000000000..f02c1eda8 --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure_float64.go @@ -0,0 +1,55 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package stats + +// Float64Measure is a measure for float64 values. +type Float64Measure struct { + desc *measureDescriptor +} + +// M creates a new float64 measurement. +// Use Record to record measurements. +func (m *Float64Measure) M(v float64) Measurement { + return Measurement{ + m: m, + desc: m.desc, + v: v, + } +} + +// Float64 creates a new measure for float64 values. +// +// See the documentation for interface Measure for more guidance on the +// parameters of this function. +func Float64(name, description, unit string) *Float64Measure { + mi := registerMeasureHandle(name, description, unit) + return &Float64Measure{mi} +} + +// Name returns the name of the measure. +func (m *Float64Measure) Name() string { + return m.desc.name +} + +// Description returns the description of the measure. +func (m *Float64Measure) Description() string { + return m.desc.description +} + +// Unit returns the unit of the measure. +func (m *Float64Measure) Unit() string { + return m.desc.unit +} diff --git a/vendor/go.opencensus.io/stats/measure_int64.go b/vendor/go.opencensus.io/stats/measure_int64.go new file mode 100644 index 000000000..d101d7973 --- /dev/null +++ b/vendor/go.opencensus.io/stats/measure_int64.go @@ -0,0 +1,55 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package stats + +// Int64Measure is a measure for int64 values. +type Int64Measure struct { + desc *measureDescriptor +} + +// M creates a new int64 measurement. +// Use Record to record measurements. +func (m *Int64Measure) M(v int64) Measurement { + return Measurement{ + m: m, + desc: m.desc, + v: float64(v), + } +} + +// Int64 creates a new measure for int64 values. +// +// See the documentation for interface Measure for more guidance on the +// parameters of this function. +func Int64(name, description, unit string) *Int64Measure { + mi := registerMeasureHandle(name, description, unit) + return &Int64Measure{mi} +} + +// Name returns the name of the measure. +func (m *Int64Measure) Name() string { + return m.desc.name +} + +// Description returns the description of the measure. +func (m *Int64Measure) Description() string { + return m.desc.description +} + +// Unit returns the unit of the measure. +func (m *Int64Measure) Unit() string { + return m.desc.unit +} diff --git a/vendor/go.opencensus.io/stats/record.go b/vendor/go.opencensus.io/stats/record.go new file mode 100644 index 000000000..ad4691184 --- /dev/null +++ b/vendor/go.opencensus.io/stats/record.go @@ -0,0 +1,117 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. +// + +package stats + +import ( + "context" + + "go.opencensus.io/metric/metricdata" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +func init() { + internal.SubscriptionReporter = func(measure string) { + mu.Lock() + measures[measure].subscribe() + mu.Unlock() + } +} + +type recordOptions struct { + attachments metricdata.Attachments + mutators []tag.Mutator + measurements []Measurement +} + +// WithAttachments applies provided exemplar attachments. +func WithAttachments(attachments metricdata.Attachments) Options { + return func(ro *recordOptions) { + ro.attachments = attachments + } +} + +// WithTags applies provided tag mutators. +func WithTags(mutators ...tag.Mutator) Options { + return func(ro *recordOptions) { + ro.mutators = mutators + } +} + +// WithMeasurements applies provided measurements. +func WithMeasurements(measurements ...Measurement) Options { + return func(ro *recordOptions) { + ro.measurements = measurements + } +} + +// Options apply changes to recordOptions. +type Options func(*recordOptions) + +func createRecordOption(ros ...Options) *recordOptions { + o := &recordOptions{} + for _, ro := range ros { + ro(o) + } + return o +} + +// Record records one or multiple measurements with the same context at once. +// If there are any tags in the context, measurements will be tagged with them. +func Record(ctx context.Context, ms ...Measurement) { + RecordWithOptions(ctx, WithMeasurements(ms...)) +} + +// RecordWithTags records one or multiple measurements at once. +// +// Measurements will be tagged with the tags in the context mutated by the mutators. +// RecordWithTags is useful if you want to record with tag mutations but don't want +// to propagate the mutations in the context. +func RecordWithTags(ctx context.Context, mutators []tag.Mutator, ms ...Measurement) error { + return RecordWithOptions(ctx, WithTags(mutators...), WithMeasurements(ms...)) +} + +// RecordWithOptions records measurements from the given options (if any) against context +// and tags and attachments in the options (if any). +// If there are any tags in the context, measurements will be tagged with them. +func RecordWithOptions(ctx context.Context, ros ...Options) error { + o := createRecordOption(ros...) + if len(o.measurements) == 0 { + return nil + } + recorder := internal.DefaultRecorder + if recorder == nil { + return nil + } + record := false + for _, m := range o.measurements { + if m.desc.subscribed() { + record = true + break + } + } + if !record { + return nil + } + if len(o.mutators) > 0 { + var err error + if ctx, err = tag.New(ctx, o.mutators...); err != nil { + return err + } + } + recorder(tag.FromContext(ctx), o.measurements, o.attachments) + return nil +} diff --git a/vendor/go.opencensus.io/stats/units.go b/vendor/go.opencensus.io/stats/units.go new file mode 100644 index 000000000..6931a5f29 --- /dev/null +++ b/vendor/go.opencensus.io/stats/units.go @@ -0,0 +1,25 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. +// + +package stats + +// Units are encoded according to the case-sensitive abbreviations from the +// Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html +const ( + UnitNone = "1" // Deprecated: Use UnitDimensionless. + UnitDimensionless = "1" + UnitBytes = "By" + UnitMilliseconds = "ms" +) diff --git a/vendor/go.opencensus.io/stats/view/aggregation.go b/vendor/go.opencensus.io/stats/view/aggregation.go new file mode 100644 index 000000000..8bd25314e --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/aggregation.go @@ -0,0 +1,120 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +// AggType represents the type of aggregation function used on a View. +type AggType int + +// All available aggregation types. +const ( + AggTypeNone AggType = iota // no aggregation; reserved for future use. + AggTypeCount // the count aggregation, see Count. + AggTypeSum // the sum aggregation, see Sum. + AggTypeDistribution // the distribution aggregation, see Distribution. + AggTypeLastValue // the last value aggregation, see LastValue. +) + +func (t AggType) String() string { + return aggTypeName[t] +} + +var aggTypeName = map[AggType]string{ + AggTypeNone: "None", + AggTypeCount: "Count", + AggTypeSum: "Sum", + AggTypeDistribution: "Distribution", + AggTypeLastValue: "LastValue", +} + +// Aggregation represents a data aggregation method. Use one of the functions: +// Count, Sum, or Distribution to construct an Aggregation. +type Aggregation struct { + Type AggType // Type is the AggType of this Aggregation. + Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution. + + newData func() AggregationData +} + +var ( + aggCount = &Aggregation{ + Type: AggTypeCount, + newData: func() AggregationData { + return &CountData{} + }, + } + aggSum = &Aggregation{ + Type: AggTypeSum, + newData: func() AggregationData { + return &SumData{} + }, + } +) + +// Count indicates that data collected and aggregated +// with this method will be turned into a count value. +// For example, total number of accepted requests can be +// aggregated by using Count. +func Count() *Aggregation { + return aggCount +} + +// Sum indicates that data collected and aggregated +// with this method will be summed up. +// For example, accumulated request bytes can be aggregated by using +// Sum. +func Sum() *Aggregation { + return aggSum +} + +// Distribution indicates that the desired aggregation is +// a histogram distribution. +// +// A distribution aggregation may contain a histogram of the values in the +// population. The bucket boundaries for that histogram are described +// by the bounds. This defines len(bounds)+1 buckets. +// +// If len(bounds) >= 2 then the boundaries for bucket index i are: +// +// [-infinity, bounds[i]) for i = 0 +// [bounds[i-1], bounds[i]) for 0 < i < length +// [bounds[i-1], +infinity) for i = length +// +// If len(bounds) is 0 then there is no histogram associated with the +// distribution. There will be a single bucket with boundaries +// (-infinity, +infinity). +// +// If len(bounds) is 1 then there is no finite buckets, and that single +// element is the common boundary of the overflow and underflow buckets. +func Distribution(bounds ...float64) *Aggregation { + return &Aggregation{ + Type: AggTypeDistribution, + Buckets: bounds, + newData: func() AggregationData { + return newDistributionData(bounds) + }, + } +} + +// LastValue only reports the last value recorded using this +// aggregation. All other measurements will be dropped. +func LastValue() *Aggregation { + return &Aggregation{ + Type: AggTypeLastValue, + newData: func() AggregationData { + return &LastValueData{} + }, + } +} diff --git a/vendor/go.opencensus.io/stats/view/aggregation_data.go b/vendor/go.opencensus.io/stats/view/aggregation_data.go new file mode 100644 index 000000000..d500e67f7 --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/aggregation_data.go @@ -0,0 +1,293 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "math" + "time" + + "go.opencensus.io/metric/metricdata" +) + +// AggregationData represents an aggregated value from a collection. +// They are reported on the view data during exporting. +// Mosts users won't directly access aggregration data. +type AggregationData interface { + isAggregationData() bool + addSample(v float64, attachments map[string]interface{}, t time.Time) + clone() AggregationData + equal(other AggregationData) bool + toPoint(t metricdata.Type, time time.Time) metricdata.Point +} + +const epsilon = 1e-9 + +// CountData is the aggregated data for the Count aggregation. +// A count aggregation processes data and counts the recordings. +// +// Most users won't directly access count data. +type CountData struct { + Value int64 +} + +func (a *CountData) isAggregationData() bool { return true } + +func (a *CountData) addSample(_ float64, _ map[string]interface{}, _ time.Time) { + a.Value = a.Value + 1 +} + +func (a *CountData) clone() AggregationData { + return &CountData{Value: a.Value} +} + +func (a *CountData) equal(other AggregationData) bool { + a2, ok := other.(*CountData) + if !ok { + return false + } + + return a.Value == a2.Value +} + +func (a *CountData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { + switch metricType { + case metricdata.TypeCumulativeInt64: + return metricdata.NewInt64Point(t, a.Value) + default: + panic("unsupported metricdata.Type") + } +} + +// SumData is the aggregated data for the Sum aggregation. +// A sum aggregation processes data and sums up the recordings. +// +// Most users won't directly access sum data. +type SumData struct { + Value float64 +} + +func (a *SumData) isAggregationData() bool { return true } + +func (a *SumData) addSample(v float64, _ map[string]interface{}, _ time.Time) { + a.Value += v +} + +func (a *SumData) clone() AggregationData { + return &SumData{Value: a.Value} +} + +func (a *SumData) equal(other AggregationData) bool { + a2, ok := other.(*SumData) + if !ok { + return false + } + return math.Pow(a.Value-a2.Value, 2) < epsilon +} + +func (a *SumData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { + switch metricType { + case metricdata.TypeCumulativeInt64: + return metricdata.NewInt64Point(t, int64(a.Value)) + case metricdata.TypeCumulativeFloat64: + return metricdata.NewFloat64Point(t, a.Value) + default: + panic("unsupported metricdata.Type") + } +} + +// DistributionData is the aggregated data for the +// Distribution aggregation. +// +// Most users won't directly access distribution data. +// +// For a distribution with N bounds, the associated DistributionData will have +// N+1 buckets. +type DistributionData struct { + Count int64 // number of data points aggregated + Min float64 // minimum value in the distribution + Max float64 // max value in the distribution + Mean float64 // mean of the distribution + SumOfSquaredDev float64 // sum of the squared deviation from the mean + CountPerBucket []int64 // number of occurrences per bucket + // ExemplarsPerBucket is slice the same length as CountPerBucket containing + // an exemplar for the associated bucket, or nil. + ExemplarsPerBucket []*metricdata.Exemplar + bounds []float64 // histogram distribution of the values +} + +func newDistributionData(bounds []float64) *DistributionData { + bucketCount := len(bounds) + 1 + return &DistributionData{ + CountPerBucket: make([]int64, bucketCount), + ExemplarsPerBucket: make([]*metricdata.Exemplar, bucketCount), + bounds: bounds, + Min: math.MaxFloat64, + Max: math.SmallestNonzeroFloat64, + } +} + +// Sum returns the sum of all samples collected. +func (a *DistributionData) Sum() float64 { return a.Mean * float64(a.Count) } + +func (a *DistributionData) variance() float64 { + if a.Count <= 1 { + return 0 + } + return a.SumOfSquaredDev / float64(a.Count-1) +} + +func (a *DistributionData) isAggregationData() bool { return true } + +// TODO(songy23): support exemplar attachments. +func (a *DistributionData) addSample(v float64, attachments map[string]interface{}, t time.Time) { + if v < a.Min { + a.Min = v + } + if v > a.Max { + a.Max = v + } + a.Count++ + a.addToBucket(v, attachments, t) + + if a.Count == 1 { + a.Mean = v + return + } + + oldMean := a.Mean + a.Mean = a.Mean + (v-a.Mean)/float64(a.Count) + a.SumOfSquaredDev = a.SumOfSquaredDev + (v-oldMean)*(v-a.Mean) +} + +func (a *DistributionData) addToBucket(v float64, attachments map[string]interface{}, t time.Time) { + var count *int64 + var i int + var b float64 + for i, b = range a.bounds { + if v < b { + count = &a.CountPerBucket[i] + break + } + } + if count == nil { // Last bucket. + i = len(a.bounds) + count = &a.CountPerBucket[i] + } + *count++ + if exemplar := getExemplar(v, attachments, t); exemplar != nil { + a.ExemplarsPerBucket[i] = exemplar + } +} + +func getExemplar(v float64, attachments map[string]interface{}, t time.Time) *metricdata.Exemplar { + if len(attachments) == 0 { + return nil + } + return &metricdata.Exemplar{ + Value: v, + Timestamp: t, + Attachments: attachments, + } +} + +func (a *DistributionData) clone() AggregationData { + c := *a + c.CountPerBucket = append([]int64(nil), a.CountPerBucket...) + c.ExemplarsPerBucket = append([]*metricdata.Exemplar(nil), a.ExemplarsPerBucket...) + return &c +} + +func (a *DistributionData) equal(other AggregationData) bool { + a2, ok := other.(*DistributionData) + if !ok { + return false + } + if a2 == nil { + return false + } + if len(a.CountPerBucket) != len(a2.CountPerBucket) { + return false + } + for i := range a.CountPerBucket { + if a.CountPerBucket[i] != a2.CountPerBucket[i] { + return false + } + } + return a.Count == a2.Count && a.Min == a2.Min && a.Max == a2.Max && math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon +} + +func (a *DistributionData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { + switch metricType { + case metricdata.TypeCumulativeDistribution: + buckets := []metricdata.Bucket{} + for i := 0; i < len(a.CountPerBucket); i++ { + buckets = append(buckets, metricdata.Bucket{ + Count: a.CountPerBucket[i], + Exemplar: a.ExemplarsPerBucket[i], + }) + } + bucketOptions := &metricdata.BucketOptions{Bounds: a.bounds} + + val := &metricdata.Distribution{ + Count: a.Count, + Sum: a.Sum(), + SumOfSquaredDeviation: a.SumOfSquaredDev, + BucketOptions: bucketOptions, + Buckets: buckets, + } + return metricdata.NewDistributionPoint(t, val) + + default: + // TODO: [rghetia] when we have a use case for TypeGaugeDistribution. + panic("unsupported metricdata.Type") + } +} + +// LastValueData returns the last value recorded for LastValue aggregation. +type LastValueData struct { + Value float64 +} + +func (l *LastValueData) isAggregationData() bool { + return true +} + +func (l *LastValueData) addSample(v float64, _ map[string]interface{}, _ time.Time) { + l.Value = v +} + +func (l *LastValueData) clone() AggregationData { + return &LastValueData{l.Value} +} + +func (l *LastValueData) equal(other AggregationData) bool { + a2, ok := other.(*LastValueData) + if !ok { + return false + } + return l.Value == a2.Value +} + +func (l *LastValueData) toPoint(metricType metricdata.Type, t time.Time) metricdata.Point { + switch metricType { + case metricdata.TypeGaugeInt64: + return metricdata.NewInt64Point(t, int64(l.Value)) + case metricdata.TypeGaugeFloat64: + return metricdata.NewFloat64Point(t, l.Value) + default: + panic("unsupported metricdata.Type") + } +} diff --git a/vendor/go.opencensus.io/stats/view/collector.go b/vendor/go.opencensus.io/stats/view/collector.go new file mode 100644 index 000000000..8a6a2c0fd --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/collector.go @@ -0,0 +1,86 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "sort" + "time" + + "go.opencensus.io/internal/tagencoding" + "go.opencensus.io/tag" +) + +type collector struct { + // signatures holds the aggregations values for each unique tag signature + // (values for all keys) to its aggregator. + signatures map[string]AggregationData + // Aggregation is the description of the aggregation to perform for this + // view. + a *Aggregation +} + +func (c *collector) addSample(s string, v float64, attachments map[string]interface{}, t time.Time) { + aggregator, ok := c.signatures[s] + if !ok { + aggregator = c.a.newData() + c.signatures[s] = aggregator + } + aggregator.addSample(v, attachments, t) +} + +// collectRows returns a snapshot of the collected Row values. +func (c *collector) collectedRows(keys []tag.Key) []*Row { + rows := make([]*Row, 0, len(c.signatures)) + for sig, aggregator := range c.signatures { + tags := decodeTags([]byte(sig), keys) + row := &Row{Tags: tags, Data: aggregator.clone()} + rows = append(rows, row) + } + return rows +} + +func (c *collector) clearRows() { + c.signatures = make(map[string]AggregationData) +} + +// encodeWithKeys encodes the map by using values +// only associated with the keys provided. +func encodeWithKeys(m *tag.Map, keys []tag.Key) []byte { + vb := &tagencoding.Values{ + Buffer: make([]byte, len(keys)), + } + for _, k := range keys { + v, _ := m.Value(k) + vb.WriteValue([]byte(v)) + } + return vb.Bytes() +} + +// decodeTags decodes tags from the buffer and +// orders them by the keys. +func decodeTags(buf []byte, keys []tag.Key) []tag.Tag { + vb := &tagencoding.Values{Buffer: buf} + var tags []tag.Tag + for _, k := range keys { + v := vb.ReadValue() + if v != nil { + tags = append(tags, tag.Tag{Key: k, Value: string(v)}) + } + } + vb.ReadIndex = 0 + sort.Slice(tags, func(i, j int) bool { return tags[i].Key.Name() < tags[j].Key.Name() }) + return tags +} diff --git a/vendor/go.opencensus.io/stats/view/doc.go b/vendor/go.opencensus.io/stats/view/doc.go new file mode 100644 index 000000000..7bbedfe1f --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/doc.go @@ -0,0 +1,47 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +// Package view contains support for collecting and exposing aggregates over stats. +// +// In order to collect measurements, views need to be defined and registered. +// A view allows recorded measurements to be filtered and aggregated. +// +// All recorded measurements can be grouped by a list of tags. +// +// OpenCensus provides several aggregation methods: Count, Distribution and Sum. +// +// Count only counts the number of measurement points recorded. +// Distribution provides statistical summary of the aggregated data by counting +// how many recorded measurements fall into each bucket. +// Sum adds up the measurement values. +// LastValue just keeps track of the most recently recorded measurement value. +// All aggregations are cumulative. +// +// Views can be registered and unregistered at any time during program execution. +// +// Libraries can define views but it is recommended that in most cases registering +// views be left up to applications. +// +// Exporting +// +// Collected and aggregated data can be exported to a metric collection +// backend by registering its exporter. +// +// Multiple exporters can be registered to upload the data to various +// different back ends. +package view // import "go.opencensus.io/stats/view" + +// TODO(acetechnologist): Add a link to the language independent OpenCensus +// spec when it is available. diff --git a/vendor/go.opencensus.io/stats/view/export.go b/vendor/go.opencensus.io/stats/view/export.go new file mode 100644 index 000000000..7cb59718f --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/export.go @@ -0,0 +1,58 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. + +package view + +import "sync" + +var ( + exportersMu sync.RWMutex // guards exporters + exporters = make(map[Exporter]struct{}) +) + +// Exporter exports the collected records as view data. +// +// The ExportView method should return quickly; if an +// Exporter takes a significant amount of time to +// process a Data, that work should be done on another goroutine. +// +// It is safe to assume that ExportView will not be called concurrently from +// multiple goroutines. +// +// The Data should not be modified. +type Exporter interface { + ExportView(viewData *Data) +} + +// RegisterExporter registers an exporter. +// Collected data will be reported via all the +// registered exporters. Once you no longer +// want data to be exported, invoke UnregisterExporter +// with the previously registered exporter. +// +// Binaries can register exporters, libraries shouldn't register exporters. +func RegisterExporter(e Exporter) { + exportersMu.Lock() + defer exportersMu.Unlock() + + exporters[e] = struct{}{} +} + +// UnregisterExporter unregisters an exporter. +func UnregisterExporter(e Exporter) { + exportersMu.Lock() + defer exportersMu.Unlock() + + delete(exporters, e) +} diff --git a/vendor/go.opencensus.io/stats/view/view.go b/vendor/go.opencensus.io/stats/view/view.go new file mode 100644 index 000000000..293b54ecb --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/view.go @@ -0,0 +1,221 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "bytes" + "errors" + "fmt" + "reflect" + "sort" + "sync/atomic" + "time" + + "go.opencensus.io/metric/metricdata" + "go.opencensus.io/stats" + "go.opencensus.io/tag" +) + +// View allows users to aggregate the recorded stats.Measurements. +// Views need to be passed to the Register function before data will be +// collected and sent to Exporters. +type View struct { + Name string // Name of View. Must be unique. If unset, will default to the name of the Measure. + Description string // Description is a human-readable description for this view. + + // TagKeys are the tag keys describing the grouping of this view. + // A single Row will be produced for each combination of associated tag values. + TagKeys []tag.Key + + // Measure is a stats.Measure to aggregate in this view. + Measure stats.Measure + + // Aggregation is the aggregation function to apply to the set of Measurements. + Aggregation *Aggregation +} + +// WithName returns a copy of the View with a new name. This is useful for +// renaming views to cope with limitations placed on metric names by various +// backends. +func (v *View) WithName(name string) *View { + vNew := *v + vNew.Name = name + return &vNew +} + +// same compares two views and returns true if they represent the same aggregation. +func (v *View) same(other *View) bool { + if v == other { + return true + } + if v == nil { + return false + } + return reflect.DeepEqual(v.Aggregation, other.Aggregation) && + v.Measure.Name() == other.Measure.Name() +} + +// ErrNegativeBucketBounds error returned if histogram contains negative bounds. +// +// Deprecated: this should not be public. +var ErrNegativeBucketBounds = errors.New("negative bucket bounds not supported") + +// canonicalize canonicalizes v by setting explicit +// defaults for Name and Description and sorting the TagKeys +func (v *View) canonicalize() error { + if v.Measure == nil { + return fmt.Errorf("cannot register view %q: measure not set", v.Name) + } + if v.Aggregation == nil { + return fmt.Errorf("cannot register view %q: aggregation not set", v.Name) + } + if v.Name == "" { + v.Name = v.Measure.Name() + } + if v.Description == "" { + v.Description = v.Measure.Description() + } + if err := checkViewName(v.Name); err != nil { + return err + } + sort.Slice(v.TagKeys, func(i, j int) bool { + return v.TagKeys[i].Name() < v.TagKeys[j].Name() + }) + sort.Float64s(v.Aggregation.Buckets) + for _, b := range v.Aggregation.Buckets { + if b < 0 { + return ErrNegativeBucketBounds + } + } + // drop 0 bucket silently. + v.Aggregation.Buckets = dropZeroBounds(v.Aggregation.Buckets...) + + return nil +} + +func dropZeroBounds(bounds ...float64) []float64 { + for i, bound := range bounds { + if bound > 0 { + return bounds[i:] + } + } + return []float64{} +} + +// viewInternal is the internal representation of a View. +type viewInternal struct { + view *View // view is the canonicalized View definition associated with this view. + subscribed uint32 // 1 if someone is subscribed and data need to be exported, use atomic to access + collector *collector + metricDescriptor *metricdata.Descriptor +} + +func newViewInternal(v *View) (*viewInternal, error) { + return &viewInternal{ + view: v, + collector: &collector{make(map[string]AggregationData), v.Aggregation}, + metricDescriptor: viewToMetricDescriptor(v), + }, nil +} + +func (v *viewInternal) subscribe() { + atomic.StoreUint32(&v.subscribed, 1) +} + +func (v *viewInternal) unsubscribe() { + atomic.StoreUint32(&v.subscribed, 0) +} + +// isSubscribed returns true if the view is exporting +// data by subscription. +func (v *viewInternal) isSubscribed() bool { + return atomic.LoadUint32(&v.subscribed) == 1 +} + +func (v *viewInternal) clearRows() { + v.collector.clearRows() +} + +func (v *viewInternal) collectedRows() []*Row { + return v.collector.collectedRows(v.view.TagKeys) +} + +func (v *viewInternal) addSample(m *tag.Map, val float64, attachments map[string]interface{}, t time.Time) { + if !v.isSubscribed() { + return + } + sig := string(encodeWithKeys(m, v.view.TagKeys)) + v.collector.addSample(sig, val, attachments, t) +} + +// A Data is a set of rows about usage of the single measure associated +// with the given view. Each row is specific to a unique set of tags. +type Data struct { + View *View + Start, End time.Time + Rows []*Row +} + +// Row is the collected value for a specific set of key value pairs a.k.a tags. +type Row struct { + Tags []tag.Tag + Data AggregationData +} + +func (r *Row) String() string { + var buffer bytes.Buffer + buffer.WriteString("{ ") + buffer.WriteString("{ ") + for _, t := range r.Tags { + buffer.WriteString(fmt.Sprintf("{%v %v}", t.Key.Name(), t.Value)) + } + buffer.WriteString(" }") + buffer.WriteString(fmt.Sprintf("%v", r.Data)) + buffer.WriteString(" }") + return buffer.String() +} + +// Equal returns true if both rows are equal. Tags are expected to be ordered +// by the key name. Even if both rows have the same tags but the tags appear in +// different orders it will return false. +func (r *Row) Equal(other *Row) bool { + if r == other { + return true + } + return reflect.DeepEqual(r.Tags, other.Tags) && r.Data.equal(other.Data) +} + +const maxNameLength = 255 + +// Returns true if the given string contains only printable characters. +func isPrintable(str string) bool { + for _, r := range str { + if !(r >= ' ' && r <= '~') { + return false + } + } + return true +} + +func checkViewName(name string) error { + if len(name) > maxNameLength { + return fmt.Errorf("view name cannot be larger than %v", maxNameLength) + } + if !isPrintable(name) { + return fmt.Errorf("view name needs to be an ASCII string") + } + return nil +} diff --git a/vendor/go.opencensus.io/stats/view/view_to_metric.go b/vendor/go.opencensus.io/stats/view/view_to_metric.go new file mode 100644 index 000000000..293c1646d --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/view_to_metric.go @@ -0,0 +1,149 @@ +// Copyright 2019, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "time" + + "go.opencensus.io/metric/metricdata" + "go.opencensus.io/stats" +) + +func getUnit(unit string) metricdata.Unit { + switch unit { + case "1": + return metricdata.UnitDimensionless + case "ms": + return metricdata.UnitMilliseconds + case "By": + return metricdata.UnitBytes + } + return metricdata.UnitDimensionless +} + +func getType(v *View) metricdata.Type { + m := v.Measure + agg := v.Aggregation + + switch agg.Type { + case AggTypeSum: + switch m.(type) { + case *stats.Int64Measure: + return metricdata.TypeCumulativeInt64 + case *stats.Float64Measure: + return metricdata.TypeCumulativeFloat64 + default: + panic("unexpected measure type") + } + case AggTypeDistribution: + return metricdata.TypeCumulativeDistribution + case AggTypeLastValue: + switch m.(type) { + case *stats.Int64Measure: + return metricdata.TypeGaugeInt64 + case *stats.Float64Measure: + return metricdata.TypeGaugeFloat64 + default: + panic("unexpected measure type") + } + case AggTypeCount: + switch m.(type) { + case *stats.Int64Measure: + return metricdata.TypeCumulativeInt64 + case *stats.Float64Measure: + return metricdata.TypeCumulativeInt64 + default: + panic("unexpected measure type") + } + default: + panic("unexpected aggregation type") + } +} + +func getLabelKeys(v *View) []metricdata.LabelKey { + labelKeys := []metricdata.LabelKey{} + for _, k := range v.TagKeys { + labelKeys = append(labelKeys, metricdata.LabelKey{Key: k.Name()}) + } + return labelKeys +} + +func viewToMetricDescriptor(v *View) *metricdata.Descriptor { + return &metricdata.Descriptor{ + Name: v.Name, + Description: v.Description, + Unit: convertUnit(v), + Type: getType(v), + LabelKeys: getLabelKeys(v), + } +} + +func convertUnit(v *View) metricdata.Unit { + switch v.Aggregation.Type { + case AggTypeCount: + return metricdata.UnitDimensionless + default: + return getUnit(v.Measure.Unit()) + } +} + +func toLabelValues(row *Row, expectedKeys []metricdata.LabelKey) []metricdata.LabelValue { + labelValues := []metricdata.LabelValue{} + tagMap := make(map[string]string) + for _, tag := range row.Tags { + tagMap[tag.Key.Name()] = tag.Value + } + + for _, key := range expectedKeys { + if val, ok := tagMap[key.Key]; ok { + labelValues = append(labelValues, metricdata.NewLabelValue(val)) + } else { + labelValues = append(labelValues, metricdata.LabelValue{}) + } + } + return labelValues +} + +func rowToTimeseries(v *viewInternal, row *Row, now time.Time, startTime time.Time) *metricdata.TimeSeries { + return &metricdata.TimeSeries{ + Points: []metricdata.Point{row.Data.toPoint(v.metricDescriptor.Type, now)}, + LabelValues: toLabelValues(row, v.metricDescriptor.LabelKeys), + StartTime: startTime, + } +} + +func viewToMetric(v *viewInternal, now time.Time, startTime time.Time) *metricdata.Metric { + if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 || + v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 { + startTime = time.Time{} + } + + rows := v.collectedRows() + if len(rows) == 0 { + return nil + } + + ts := []*metricdata.TimeSeries{} + for _, row := range rows { + ts = append(ts, rowToTimeseries(v, row, now, startTime)) + } + + m := &metricdata.Metric{ + Descriptor: *v.metricDescriptor, + TimeSeries: ts, + } + return m +} diff --git a/vendor/go.opencensus.io/stats/view/worker.go b/vendor/go.opencensus.io/stats/view/worker.go new file mode 100644 index 000000000..2f3c018af --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/worker.go @@ -0,0 +1,281 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "fmt" + "sync" + "time" + + "go.opencensus.io/metric/metricdata" + "go.opencensus.io/metric/metricproducer" + "go.opencensus.io/stats" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +func init() { + defaultWorker = newWorker() + go defaultWorker.start() + internal.DefaultRecorder = record +} + +type measureRef struct { + measure string + views map[*viewInternal]struct{} +} + +type worker struct { + measures map[string]*measureRef + views map[string]*viewInternal + startTimes map[*viewInternal]time.Time + + timer *time.Ticker + c chan command + quit, done chan bool + mu sync.RWMutex +} + +var defaultWorker *worker + +var defaultReportingDuration = 10 * time.Second + +// Find returns a registered view associated with this name. +// If no registered view is found, nil is returned. +func Find(name string) (v *View) { + req := &getViewByNameReq{ + name: name, + c: make(chan *getViewByNameResp), + } + defaultWorker.c <- req + resp := <-req.c + return resp.v +} + +// Register begins collecting data for the given views. +// Once a view is registered, it reports data to the registered exporters. +func Register(views ...*View) error { + req := ®isterViewReq{ + views: views, + err: make(chan error), + } + defaultWorker.c <- req + return <-req.err +} + +// Unregister the given views. Data will not longer be exported for these views +// after Unregister returns. +// It is not necessary to unregister from views you expect to collect for the +// duration of your program execution. +func Unregister(views ...*View) { + names := make([]string, len(views)) + for i := range views { + names[i] = views[i].Name + } + req := &unregisterFromViewReq{ + views: names, + done: make(chan struct{}), + } + defaultWorker.c <- req + <-req.done +} + +// RetrieveData gets a snapshot of the data collected for the the view registered +// with the given name. It is intended for testing only. +func RetrieveData(viewName string) ([]*Row, error) { + req := &retrieveDataReq{ + now: time.Now(), + v: viewName, + c: make(chan *retrieveDataResp), + } + defaultWorker.c <- req + resp := <-req.c + return resp.rows, resp.err +} + +func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) { + req := &recordReq{ + tm: tags, + ms: ms.([]stats.Measurement), + attachments: attachments, + t: time.Now(), + } + defaultWorker.c <- req +} + +// SetReportingPeriod sets the interval between reporting aggregated views in +// the program. If duration is less than or equal to zero, it enables the +// default behavior. +// +// Note: each exporter makes different promises about what the lowest supported +// duration is. For example, the Stackdriver exporter recommends a value no +// lower than 1 minute. Consult each exporter per your needs. +func SetReportingPeriod(d time.Duration) { + // TODO(acetechnologist): ensure that the duration d is more than a certain + // value. e.g. 1s + req := &setReportingPeriodReq{ + d: d, + c: make(chan bool), + } + defaultWorker.c <- req + <-req.c // don't return until the timer is set to the new duration. +} + +func newWorker() *worker { + return &worker{ + measures: make(map[string]*measureRef), + views: make(map[string]*viewInternal), + startTimes: make(map[*viewInternal]time.Time), + timer: time.NewTicker(defaultReportingDuration), + c: make(chan command, 1024), + quit: make(chan bool), + done: make(chan bool), + } +} + +func (w *worker) start() { + prodMgr := metricproducer.GlobalManager() + prodMgr.AddProducer(w) + + for { + select { + case cmd := <-w.c: + cmd.handleCommand(w) + case <-w.timer.C: + w.reportUsage(time.Now()) + case <-w.quit: + w.timer.Stop() + close(w.c) + w.done <- true + return + } + } +} + +func (w *worker) stop() { + prodMgr := metricproducer.GlobalManager() + prodMgr.DeleteProducer(w) + + w.quit <- true + <-w.done +} + +func (w *worker) getMeasureRef(name string) *measureRef { + if mr, ok := w.measures[name]; ok { + return mr + } + mr := &measureRef{ + measure: name, + views: make(map[*viewInternal]struct{}), + } + w.measures[name] = mr + return mr +} + +func (w *worker) tryRegisterView(v *View) (*viewInternal, error) { + w.mu.Lock() + defer w.mu.Unlock() + vi, err := newViewInternal(v) + if err != nil { + return nil, err + } + if x, ok := w.views[vi.view.Name]; ok { + if !x.view.same(vi.view) { + return nil, fmt.Errorf("cannot register view %q; a different view with the same name is already registered", v.Name) + } + + // the view is already registered so there is nothing to do and the + // command is considered successful. + return x, nil + } + w.views[vi.view.Name] = vi + ref := w.getMeasureRef(vi.view.Measure.Name()) + ref.views[vi] = struct{}{} + return vi, nil +} + +func (w *worker) unregisterView(viewName string) { + w.mu.Lock() + defer w.mu.Unlock() + delete(w.views, viewName) +} + +func (w *worker) reportView(v *viewInternal, now time.Time) { + if !v.isSubscribed() { + return + } + rows := v.collectedRows() + _, ok := w.startTimes[v] + if !ok { + w.startTimes[v] = now + } + viewData := &Data{ + View: v.view, + Start: w.startTimes[v], + End: time.Now(), + Rows: rows, + } + exportersMu.Lock() + for e := range exporters { + e.ExportView(viewData) + } + exportersMu.Unlock() +} + +func (w *worker) reportUsage(now time.Time) { + w.mu.Lock() + defer w.mu.Unlock() + for _, v := range w.views { + w.reportView(v, now) + } +} + +func (w *worker) toMetric(v *viewInternal, now time.Time) *metricdata.Metric { + if !v.isSubscribed() { + return nil + } + + _, ok := w.startTimes[v] + if !ok { + w.startTimes[v] = now + } + + var startTime time.Time + if v.metricDescriptor.Type == metricdata.TypeGaugeInt64 || + v.metricDescriptor.Type == metricdata.TypeGaugeFloat64 { + startTime = time.Time{} + } else { + startTime = w.startTimes[v] + } + + return viewToMetric(v, now, startTime) +} + +// Read reads all view data and returns them as metrics. +// It is typically invoked by metric reader to export stats in metric format. +func (w *worker) Read() []*metricdata.Metric { + w.mu.Lock() + defer w.mu.Unlock() + now := time.Now() + metrics := make([]*metricdata.Metric, 0, len(w.views)) + for _, v := range w.views { + metric := w.toMetric(v, now) + if metric != nil { + metrics = append(metrics, metric) + } + } + return metrics +} diff --git a/vendor/go.opencensus.io/stats/view/worker_commands.go b/vendor/go.opencensus.io/stats/view/worker_commands.go new file mode 100644 index 000000000..0267e179a --- /dev/null +++ b/vendor/go.opencensus.io/stats/view/worker_commands.go @@ -0,0 +1,186 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package view + +import ( + "errors" + "fmt" + "strings" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +type command interface { + handleCommand(w *worker) +} + +// getViewByNameReq is the command to get a view given its name. +type getViewByNameReq struct { + name string + c chan *getViewByNameResp +} + +type getViewByNameResp struct { + v *View +} + +func (cmd *getViewByNameReq) handleCommand(w *worker) { + v := w.views[cmd.name] + if v == nil { + cmd.c <- &getViewByNameResp{nil} + return + } + cmd.c <- &getViewByNameResp{v.view} +} + +// registerViewReq is the command to register a view. +type registerViewReq struct { + views []*View + err chan error +} + +func (cmd *registerViewReq) handleCommand(w *worker) { + for _, v := range cmd.views { + if err := v.canonicalize(); err != nil { + cmd.err <- err + return + } + } + var errstr []string + for _, view := range cmd.views { + vi, err := w.tryRegisterView(view) + if err != nil { + errstr = append(errstr, fmt.Sprintf("%s: %v", view.Name, err)) + continue + } + internal.SubscriptionReporter(view.Measure.Name()) + vi.subscribe() + } + if len(errstr) > 0 { + cmd.err <- errors.New(strings.Join(errstr, "\n")) + } else { + cmd.err <- nil + } +} + +// unregisterFromViewReq is the command to unregister to a view. Has no +// impact on the data collection for client that are pulling data from the +// library. +type unregisterFromViewReq struct { + views []string + done chan struct{} +} + +func (cmd *unregisterFromViewReq) handleCommand(w *worker) { + for _, name := range cmd.views { + vi, ok := w.views[name] + if !ok { + continue + } + + // Report pending data for this view before removing it. + w.reportView(vi, time.Now()) + + vi.unsubscribe() + if !vi.isSubscribed() { + // this was the last subscription and view is not collecting anymore. + // The collected data can be cleared. + vi.clearRows() + } + w.unregisterView(name) + } + cmd.done <- struct{}{} +} + +// retrieveDataReq is the command to retrieve data for a view. +type retrieveDataReq struct { + now time.Time + v string + c chan *retrieveDataResp +} + +type retrieveDataResp struct { + rows []*Row + err error +} + +func (cmd *retrieveDataReq) handleCommand(w *worker) { + w.mu.Lock() + defer w.mu.Unlock() + vi, ok := w.views[cmd.v] + if !ok { + cmd.c <- &retrieveDataResp{ + nil, + fmt.Errorf("cannot retrieve data; view %q is not registered", cmd.v), + } + return + } + + if !vi.isSubscribed() { + cmd.c <- &retrieveDataResp{ + nil, + fmt.Errorf("cannot retrieve data; view %q has no subscriptions or collection is not forcibly started", cmd.v), + } + return + } + cmd.c <- &retrieveDataResp{ + vi.collectedRows(), + nil, + } +} + +// recordReq is the command to record data related to multiple measures +// at once. +type recordReq struct { + tm *tag.Map + ms []stats.Measurement + attachments map[string]interface{} + t time.Time +} + +func (cmd *recordReq) handleCommand(w *worker) { + w.mu.Lock() + defer w.mu.Unlock() + for _, m := range cmd.ms { + if (m == stats.Measurement{}) { // not registered + continue + } + ref := w.getMeasureRef(m.Measure().Name()) + for v := range ref.views { + v.addSample(cmd.tm, m.Value(), cmd.attachments, time.Now()) + } + } +} + +// setReportingPeriodReq is the command to modify the duration between +// reporting the collected data to the registered clients. +type setReportingPeriodReq struct { + d time.Duration + c chan bool +} + +func (cmd *setReportingPeriodReq) handleCommand(w *worker) { + w.timer.Stop() + if cmd.d <= 0 { + w.timer = time.NewTicker(defaultReportingDuration) + } else { + w.timer = time.NewTicker(cmd.d) + } + cmd.c <- true +} diff --git a/vendor/go.opencensus.io/tag/context.go b/vendor/go.opencensus.io/tag/context.go new file mode 100644 index 000000000..b27d1b26b --- /dev/null +++ b/vendor/go.opencensus.io/tag/context.go @@ -0,0 +1,43 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package tag + +import ( + "context" +) + +// FromContext returns the tag map stored in the context. +func FromContext(ctx context.Context) *Map { + // The returned tag map shouldn't be mutated. + ts := ctx.Value(mapCtxKey) + if ts == nil { + return nil + } + return ts.(*Map) +} + +// NewContext creates a new context with the given tag map. +// To propagate a tag map to downstream methods and downstream RPCs, add a tag map +// to the current context. NewContext will return a copy of the current context, +// and put the tag map into the returned one. +// If there is already a tag map in the current context, it will be replaced with m. +func NewContext(ctx context.Context, m *Map) context.Context { + return context.WithValue(ctx, mapCtxKey, m) +} + +type ctxKey struct{} + +var mapCtxKey = ctxKey{} diff --git a/vendor/go.opencensus.io/tag/doc.go b/vendor/go.opencensus.io/tag/doc.go new file mode 100644 index 000000000..da16b74e4 --- /dev/null +++ b/vendor/go.opencensus.io/tag/doc.go @@ -0,0 +1,26 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +/* +Package tag contains OpenCensus tags. + +Tags are key-value pairs. Tags provide additional cardinality to +the OpenCensus instrumentation data. + +Tags can be propagated on the wire and in the same +process via context.Context. Encode and Decode should be +used to represent tags into their binary propagation form. +*/ +package tag // import "go.opencensus.io/tag" diff --git a/vendor/go.opencensus.io/tag/key.go b/vendor/go.opencensus.io/tag/key.go new file mode 100644 index 000000000..71ec91365 --- /dev/null +++ b/vendor/go.opencensus.io/tag/key.go @@ -0,0 +1,44 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package tag + +// Key represents a tag key. +type Key struct { + name string +} + +// NewKey creates or retrieves a string key identified by name. +// Calling NewKey more than once with the same name returns the same key. +func NewKey(name string) (Key, error) { + if !checkKeyName(name) { + return Key{}, errInvalidKeyName + } + return Key{name: name}, nil +} + +// MustNewKey returns a key with the given name, and panics if name is an invalid key name. +func MustNewKey(name string) Key { + k, err := NewKey(name) + if err != nil { + panic(err) + } + return k +} + +// Name returns the name of the key. +func (k Key) Name() string { + return k.name +} diff --git a/vendor/go.opencensus.io/tag/map.go b/vendor/go.opencensus.io/tag/map.go new file mode 100644 index 000000000..0272ef85a --- /dev/null +++ b/vendor/go.opencensus.io/tag/map.go @@ -0,0 +1,229 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package tag + +import ( + "bytes" + "context" + "fmt" + "sort" +) + +// Tag is a key value pair that can be propagated on wire. +type Tag struct { + Key Key + Value string +} + +type tagContent struct { + value string + m metadatas +} + +// Map is a map of tags. Use New to create a context containing +// a new Map. +type Map struct { + m map[Key]tagContent +} + +// Value returns the value for the key if a value for the key exists. +func (m *Map) Value(k Key) (string, bool) { + if m == nil { + return "", false + } + v, ok := m.m[k] + return v.value, ok +} + +func (m *Map) String() string { + if m == nil { + return "nil" + } + keys := make([]Key, 0, len(m.m)) + for k := range m.m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() }) + + var buffer bytes.Buffer + buffer.WriteString("{ ") + for _, k := range keys { + buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k])) + } + buffer.WriteString(" }") + return buffer.String() +} + +func (m *Map) insert(k Key, v string, md metadatas) { + if _, ok := m.m[k]; ok { + return + } + m.m[k] = tagContent{value: v, m: md} +} + +func (m *Map) update(k Key, v string, md metadatas) { + if _, ok := m.m[k]; ok { + m.m[k] = tagContent{value: v, m: md} + } +} + +func (m *Map) upsert(k Key, v string, md metadatas) { + m.m[k] = tagContent{value: v, m: md} +} + +func (m *Map) delete(k Key) { + delete(m.m, k) +} + +func newMap() *Map { + return &Map{m: make(map[Key]tagContent)} +} + +// Mutator modifies a tag map. +type Mutator interface { + Mutate(t *Map) (*Map, error) +} + +// Insert returns a mutator that inserts a +// value associated with k. If k already exists in the tag map, +// mutator doesn't update the value. +// Metadata applies metadata to the tag. It is optional. +// Metadatas are applied in the order in which it is provided. +// If more than one metadata updates the same attribute then +// the update from the last metadata prevails. +func Insert(k Key, v string, mds ...Metadata) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.insert(k, v, createMetadatas(mds...)) + return m, nil + }, + } +} + +// Update returns a mutator that updates the +// value of the tag associated with k with v. If k doesn't +// exists in the tag map, the mutator doesn't insert the value. +// Metadata applies metadata to the tag. It is optional. +// Metadatas are applied in the order in which it is provided. +// If more than one metadata updates the same attribute then +// the update from the last metadata prevails. +func Update(k Key, v string, mds ...Metadata) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.update(k, v, createMetadatas(mds...)) + return m, nil + }, + } +} + +// Upsert returns a mutator that upserts the +// value of the tag associated with k with v. It inserts the +// value if k doesn't exist already. It mutates the value +// if k already exists. +// Metadata applies metadata to the tag. It is optional. +// Metadatas are applied in the order in which it is provided. +// If more than one metadata updates the same attribute then +// the update from the last metadata prevails. +func Upsert(k Key, v string, mds ...Metadata) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.upsert(k, v, createMetadatas(mds...)) + return m, nil + }, + } +} + +func createMetadatas(mds ...Metadata) metadatas { + var metas metadatas + if len(mds) > 0 { + for _, md := range mds { + if md != nil { + md(&metas) + } + } + } else { + WithTTL(TTLUnlimitedPropagation)(&metas) + } + return metas + +} + +// Delete returns a mutator that deletes +// the value associated with k. +func Delete(k Key) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + m.delete(k) + return m, nil + }, + } +} + +// New returns a new context that contains a tag map +// originated from the incoming context and modified +// with the provided mutators. +func New(ctx context.Context, mutator ...Mutator) (context.Context, error) { + m := newMap() + orig := FromContext(ctx) + if orig != nil { + for k, v := range orig.m { + if !checkKeyName(k.Name()) { + return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName) + } + if !checkValue(v.value) { + return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue) + } + m.insert(k, v.value, v.m) + } + } + var err error + for _, mod := range mutator { + m, err = mod.Mutate(m) + if err != nil { + return ctx, err + } + } + return NewContext(ctx, m), nil +} + +// Do is similar to pprof.Do: a convenience for installing the tags +// from the context as Go profiler labels. This allows you to +// correlated runtime profiling with stats. +// +// It converts the key/values from the given map to Go profiler labels +// and calls pprof.Do. +// +// Do is going to do nothing if your Go version is below 1.9. +func Do(ctx context.Context, f func(ctx context.Context)) { + do(ctx, f) +} + +type mutator struct { + fn func(t *Map) (*Map, error) +} + +func (m *mutator) Mutate(t *Map) (*Map, error) { + return m.fn(t) +} diff --git a/vendor/go.opencensus.io/tag/map_codec.go b/vendor/go.opencensus.io/tag/map_codec.go new file mode 100644 index 000000000..c242e695c --- /dev/null +++ b/vendor/go.opencensus.io/tag/map_codec.go @@ -0,0 +1,239 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. +// + +package tag + +import ( + "encoding/binary" + "fmt" +) + +// KeyType defines the types of keys allowed. Currently only keyTypeString is +// supported. +type keyType byte + +const ( + keyTypeString keyType = iota + keyTypeInt64 + keyTypeTrue + keyTypeFalse + + tagsVersionID = byte(0) +) + +type encoderGRPC struct { + buf []byte + writeIdx, readIdx int +} + +// writeKeyString writes the fieldID '0' followed by the key string and value +// string. +func (eg *encoderGRPC) writeTagString(k, v string) { + eg.writeByte(byte(keyTypeString)) + eg.writeStringWithVarintLen(k) + eg.writeStringWithVarintLen(v) +} + +func (eg *encoderGRPC) writeTagUint64(k string, i uint64) { + eg.writeByte(byte(keyTypeInt64)) + eg.writeStringWithVarintLen(k) + eg.writeUint64(i) +} + +func (eg *encoderGRPC) writeTagTrue(k string) { + eg.writeByte(byte(keyTypeTrue)) + eg.writeStringWithVarintLen(k) +} + +func (eg *encoderGRPC) writeTagFalse(k string) { + eg.writeByte(byte(keyTypeFalse)) + eg.writeStringWithVarintLen(k) +} + +func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) { + length := len(bytes) + + eg.growIfRequired(binary.MaxVarintLen64 + length) + eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) + copy(eg.buf[eg.writeIdx:], bytes) + eg.writeIdx += length +} + +func (eg *encoderGRPC) writeStringWithVarintLen(s string) { + length := len(s) + + eg.growIfRequired(binary.MaxVarintLen64 + length) + eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) + copy(eg.buf[eg.writeIdx:], s) + eg.writeIdx += length +} + +func (eg *encoderGRPC) writeByte(v byte) { + eg.growIfRequired(1) + eg.buf[eg.writeIdx] = v + eg.writeIdx++ +} + +func (eg *encoderGRPC) writeUint32(i uint32) { + eg.growIfRequired(4) + binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i) + eg.writeIdx += 4 +} + +func (eg *encoderGRPC) writeUint64(i uint64) { + eg.growIfRequired(8) + binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i) + eg.writeIdx += 8 +} + +func (eg *encoderGRPC) readByte() byte { + b := eg.buf[eg.readIdx] + eg.readIdx++ + return b +} + +func (eg *encoderGRPC) readUint32() uint32 { + i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:]) + eg.readIdx += 4 + return i +} + +func (eg *encoderGRPC) readUint64() uint64 { + i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:]) + eg.readIdx += 8 + return i +} + +func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) { + if eg.readEnded() { + return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) + } + length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:]) + if valueStart <= 0 { + return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) + } + + valueStart += eg.readIdx + valueEnd := valueStart + int(length) + if valueEnd > len(eg.buf) { + return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf)) + } + + eg.readIdx = valueEnd + return eg.buf[valueStart:valueEnd], nil +} + +func (eg *encoderGRPC) readStringWithVarintLen() (string, error) { + bytes, err := eg.readBytesWithVarintLen() + if err != nil { + return "", err + } + return string(bytes), nil +} + +func (eg *encoderGRPC) growIfRequired(expected int) { + if len(eg.buf)-eg.writeIdx < expected { + tmp := make([]byte, 2*(len(eg.buf)+1)+expected) + copy(tmp, eg.buf) + eg.buf = tmp + } +} + +func (eg *encoderGRPC) readEnded() bool { + return eg.readIdx >= len(eg.buf) +} + +func (eg *encoderGRPC) bytes() []byte { + return eg.buf[:eg.writeIdx] +} + +// Encode encodes the tag map into a []byte. It is useful to propagate +// the tag maps on wire in binary format. +func Encode(m *Map) []byte { + if m == nil { + return nil + } + eg := &encoderGRPC{ + buf: make([]byte, len(m.m)), + } + eg.writeByte(tagsVersionID) + for k, v := range m.m { + if v.m.ttl.ttl == valueTTLUnlimitedPropagation { + eg.writeByte(byte(keyTypeString)) + eg.writeStringWithVarintLen(k.name) + eg.writeBytesWithVarintLen([]byte(v.value)) + } + } + return eg.bytes() +} + +// Decode decodes the given []byte into a tag map. +func Decode(bytes []byte) (*Map, error) { + ts := newMap() + err := DecodeEach(bytes, ts.upsert) + if err != nil { + // no partial failures + return nil, err + } + return ts, nil +} + +// DecodeEach decodes the given serialized tag map, calling handler for each +// tag key and value decoded. +func DecodeEach(bytes []byte, fn func(key Key, val string, md metadatas)) error { + eg := &encoderGRPC{ + buf: bytes, + } + if len(eg.buf) == 0 { + return nil + } + + version := eg.readByte() + if version > tagsVersionID { + return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID) + } + + for !eg.readEnded() { + typ := keyType(eg.readByte()) + + if typ != keyTypeString { + return fmt.Errorf("cannot decode: invalid key type: %q", typ) + } + + k, err := eg.readBytesWithVarintLen() + if err != nil { + return err + } + + v, err := eg.readBytesWithVarintLen() + if err != nil { + return err + } + + key, err := NewKey(string(k)) + if err != nil { + return err + } + val := string(v) + if !checkValue(val) { + return errInvalidValue + } + fn(key, val, createMetadatas(WithTTL(TTLUnlimitedPropagation))) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/go.opencensus.io/tag/metadata.go b/vendor/go.opencensus.io/tag/metadata.go new file mode 100644 index 000000000..6571a583e --- /dev/null +++ b/vendor/go.opencensus.io/tag/metadata.go @@ -0,0 +1,52 @@ +// Copyright 2019, OpenCensus Authors +// +// 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. +// + +package tag + +const ( + // valueTTLNoPropagation prevents tag from propagating. + valueTTLNoPropagation = 0 + + // valueTTLUnlimitedPropagation allows tag to propagate without any limits on number of hops. + valueTTLUnlimitedPropagation = -1 +) + +// TTL is metadata that specifies number of hops a tag can propagate. +// Details about TTL metadata is specified at https://github.com/census-instrumentation/opencensus-specs/blob/master/tags/TagMap.md#tagmetadata +type TTL struct { + ttl int +} + +var ( + // TTLUnlimitedPropagation is TTL metadata that allows tag to propagate without any limits on number of hops. + TTLUnlimitedPropagation = TTL{ttl: valueTTLUnlimitedPropagation} + + // TTLNoPropagation is TTL metadata that prevents tag from propagating. + TTLNoPropagation = TTL{ttl: valueTTLNoPropagation} +) + +type metadatas struct { + ttl TTL +} + +// Metadata applies metadatas specified by the function. +type Metadata func(*metadatas) + +// WithTTL applies metadata with provided ttl. +func WithTTL(ttl TTL) Metadata { + return func(m *metadatas) { + m.ttl = ttl + } +} diff --git a/vendor/go.opencensus.io/tag/profile_19.go b/vendor/go.opencensus.io/tag/profile_19.go new file mode 100644 index 000000000..b34d95e34 --- /dev/null +++ b/vendor/go.opencensus.io/tag/profile_19.go @@ -0,0 +1,31 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +// +build go1.9 + +package tag + +import ( + "context" + "runtime/pprof" +) + +func do(ctx context.Context, f func(ctx context.Context)) { + m := FromContext(ctx) + keyvals := make([]string, 0, 2*len(m.m)) + for k, v := range m.m { + keyvals = append(keyvals, k.Name(), v.value) + } + pprof.Do(ctx, pprof.Labels(keyvals...), f) +} diff --git a/vendor/go.opencensus.io/tag/profile_not19.go b/vendor/go.opencensus.io/tag/profile_not19.go new file mode 100644 index 000000000..83adbce56 --- /dev/null +++ b/vendor/go.opencensus.io/tag/profile_not19.go @@ -0,0 +1,23 @@ +// Copyright 2018, OpenCensus Authors +// +// 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. + +// +build !go1.9 + +package tag + +import "context" + +func do(ctx context.Context, f func(ctx context.Context)) { + f(ctx) +} diff --git a/vendor/go.opencensus.io/tag/validate.go b/vendor/go.opencensus.io/tag/validate.go new file mode 100644 index 000000000..0939fc674 --- /dev/null +++ b/vendor/go.opencensus.io/tag/validate.go @@ -0,0 +1,56 @@ +// Copyright 2017, OpenCensus Authors +// +// 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. + +package tag + +import "errors" + +const ( + maxKeyLength = 255 + + // valid are restricted to US-ASCII subset (range 0x20 (' ') to 0x7e ('~')). + validKeyValueMin = 32 + validKeyValueMax = 126 +) + +var ( + errInvalidKeyName = errors.New("invalid key name: only ASCII characters accepted; max length must be 255 characters") + errInvalidValue = errors.New("invalid value: only ASCII characters accepted; max length must be 255 characters") +) + +func checkKeyName(name string) bool { + if len(name) == 0 { + return false + } + if len(name) > maxKeyLength { + return false + } + return isASCII(name) +} + +func isASCII(s string) bool { + for _, c := range s { + if (c < validKeyValueMin) || (c > validKeyValueMax) { + return false + } + } + return true +} + +func checkValue(v string) bool { + if len(v) > maxKeyLength { + return false + } + return isASCII(v) +} diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go deleted file mode 100644 index 9d80f1952..000000000 --- a/vendor/golang.org/x/crypto/blowfish/block.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blowfish - -// getNextWord returns the next big-endian uint32 value from the byte slice -// at the given position in a circular manner, updating the position. -func getNextWord(b []byte, pos *int) uint32 { - var w uint32 - j := *pos - for i := 0; i < 4; i++ { - w = w<<8 | uint32(b[j]) - j++ - if j >= len(b) { - j = 0 - } - } - *pos = j - return w -} - -// ExpandKey performs a key expansion on the given *Cipher. Specifically, it -// performs the Blowfish algorithm's key schedule which sets up the *Cipher's -// pi and substitution tables for calls to Encrypt. This is used, primarily, -// by the bcrypt package to reuse the Blowfish key schedule during its -// set up. It's unlikely that you need to use this directly. -func ExpandKey(key []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - // Using inlined getNextWord for performance. - var d uint32 - for k := 0; k < 4; k++ { - d = d<<8 | uint32(key[j]) - j++ - if j >= len(key) { - j = 0 - } - } - c.p[i] ^= d - } - - var l, r uint32 - for i := 0; i < 18; i += 2 { - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -// This is similar to ExpandKey, but folds the salt during the key -// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero -// salt passed in, reusing ExpandKey turns out to be a place of inefficiency -// and specializing it here is useful. -func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - c.p[i] ^= getNextWord(key, &j) - } - - j = 0 - var l, r uint32 - for i := 0; i < 18; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[0] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] - xr ^= c.p[17] - return xr, xl -} - -func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[17] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] - xr ^= c.p[0] - return xr, xl -} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go deleted file mode 100644 index 213bf204a..000000000 --- a/vendor/golang.org/x/crypto/blowfish/cipher.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. -// -// Blowfish is a legacy cipher and its short block size makes it vulnerable to -// birthday bound attacks (see https://sweet32.info). It should only be used -// where compatibility with legacy systems, not security, is the goal. -// -// Deprecated: any new system should use AES (from crypto/aes, if necessary in -// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -// golang.org/x/crypto/chacha20poly1305). -package blowfish // import "golang.org/x/crypto/blowfish" - -// The code is a port of Bruce Schneier's C implementation. -// See https://www.schneier.com/blowfish.html. - -import "strconv" - -// The Blowfish block size in bytes. -const BlockSize = 8 - -// A Cipher is an instance of Blowfish encryption using a particular key. -type Cipher struct { - p [18]uint32 - s0, s1, s2, s3 [256]uint32 -} - -type KeySizeError int - -func (k KeySizeError) Error() string { - return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) -} - -// NewCipher creates and returns a Cipher. -// The key argument should be the Blowfish key, from 1 to 56 bytes. -func NewCipher(key []byte) (*Cipher, error) { - var result Cipher - if k := len(key); k < 1 || k > 56 { - return nil, KeySizeError(k) - } - initCipher(&result) - ExpandKey(key, &result) - return &result, nil -} - -// NewSaltedCipher creates a returns a Cipher that folds a salt into its key -// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is -// sufficient and desirable. For bcrypt compatibility, the key can be over 56 -// bytes. -func NewSaltedCipher(key, salt []byte) (*Cipher, error) { - if len(salt) == 0 { - return NewCipher(key) - } - var result Cipher - if k := len(key); k < 1 { - return nil, KeySizeError(k) - } - initCipher(&result) - expandKeyWithSalt(key, salt, &result) - return &result, nil -} - -// BlockSize returns the Blowfish block size, 8 bytes. -// It is necessary to satisfy the Block interface in the -// package "crypto/cipher". -func (c *Cipher) BlockSize() int { return BlockSize } - -// Encrypt encrypts the 8-byte buffer src using the key k -// and stores the result in dst. -// Note that for amounts of data larger than a block, -// it is not safe to just call Encrypt on successive blocks; -// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -func (c *Cipher) Encrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = encryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -// Decrypt decrypts the 8-byte buffer src using the key k -// and stores the result in dst. -func (c *Cipher) Decrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = decryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -func initCipher(c *Cipher) { - copy(c.p[0:], p[0:]) - copy(c.s0[0:], s0[0:]) - copy(c.s1[0:], s1[0:]) - copy(c.s2[0:], s2[0:]) - copy(c.s3[0:], s3[0:]) -} diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go deleted file mode 100644 index d04077595..000000000 --- a/vendor/golang.org/x/crypto/blowfish/const.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The startup permutation array and substitution boxes. -// They are the hexadecimal digits of PI; see: -// https://www.schneier.com/code/constants.txt. - -package blowfish - -var s0 = [256]uint32{ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, -} - -var s1 = [256]uint32{ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, -} - -var s2 = [256]uint32{ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, -} - -var s3 = [256]uint32{ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -} - -var p = [18]uint32{ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, -} diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go index c4ff3f6e6..f455147d2 100644 --- a/vendor/golang.org/x/crypto/sha3/hashes_generic.go +++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build gccgo appengine !s390x +// +build gccgo appengine !s390x package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go index b6cbc5c41..c13ec85b5 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build !gccgo,!appengine +// +build !gccgo,!appengine package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s index b2ef69f8c..8a4458f63 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build !gccgo,!appengine +// +build !gccgo,!appengine #include "textflag.h" diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go index 73d0c90bf..add4e7339 100644 --- a/vendor/golang.org/x/crypto/sha3/shake_generic.go +++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build gccgo appengine !s390x +// +build gccgo appengine !s390x package sha3 diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go new file mode 100644 index 000000000..5d052781b --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -0,0 +1,712 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +//go:generate go run gen.go +//go:generate go run gen.go -test + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "io/ioutil" + "math/rand" + "os" + "sort" + "strings" +) + +// identifier converts s to a Go exported identifier. +// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". +func identifier(s string) string { + b := make([]byte, 0, len(s)) + cap := true + for _, c := range s { + if c == '-' { + cap = true + continue + } + if cap && 'a' <= c && c <= 'z' { + c -= 'a' - 'A' + } + cap = false + b = append(b, byte(c)) + } + return string(b) +} + +var test = flag.Bool("test", false, "generate table_test.go") + +func genFile(name string, buf *bytes.Buffer) { + b, err := format.Source(buf.Bytes()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := ioutil.WriteFile(name, b, 0644); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func main() { + flag.Parse() + + var all []string + all = append(all, elements...) + all = append(all, attributes...) + all = append(all, eventHandlers...) + all = append(all, extra...) + sort.Strings(all) + + // uniq - lists have dups + w := 0 + for _, s := range all { + if w == 0 || all[w-1] != s { + all[w] = s + w++ + } + } + all = all[:w] + + if *test { + var buf bytes.Buffer + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") + fmt.Fprintln(&buf, "package atom\n") + fmt.Fprintln(&buf, "var testAtomList = []string{") + for _, s := range all { + fmt.Fprintf(&buf, "\t%q,\n", s) + } + fmt.Fprintln(&buf, "}") + + genFile("table_test.go", &buf) + return + } + + // Find hash that minimizes table size. + var best *table + for i := 0; i < 1000000; i++ { + if best != nil && 1<<(best.k-1) < len(all) { + break + } + h := rand.Uint32() + for k := uint(0); k <= 16; k++ { + if best != nil && k >= best.k { + break + } + var t table + if t.init(h, k, all) { + best = &t + break + } + } + } + if best == nil { + fmt.Fprintf(os.Stderr, "failed to construct string table\n") + os.Exit(1) + } + + // Lay out strings, using overlaps when possible. + layout := append([]string{}, all...) + + // Remove strings that are substrings of other strings + for changed := true; changed; { + changed = false + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i != j && t != "" && strings.Contains(s, t) { + changed = true + layout[j] = "" + } + } + } + } + + // Join strings where one suffix matches another prefix. + for { + // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], + // maximizing overlap length k. + besti := -1 + bestj := -1 + bestk := 0 + for i, s := range layout { + if s == "" { + continue + } + for j, t := range layout { + if i == j { + continue + } + for k := bestk + 1; k <= len(s) && k <= len(t); k++ { + if s[len(s)-k:] == t[:k] { + besti = i + bestj = j + bestk = k + } + } + } + } + if bestk > 0 { + layout[besti] += layout[bestj][bestk:] + layout[bestj] = "" + continue + } + break + } + + text := strings.Join(layout, "") + + atom := map[string]uint32{} + for _, s := range all { + off := strings.Index(text, s) + if off < 0 { + panic("lost string " + s) + } + atom[s] = uint32(off<<8 | len(s)) + } + + var buf bytes.Buffer + // Generate the Go code. + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go\n") + fmt.Fprintln(&buf, "package atom\n\nconst (") + + // compute max len + maxLen := 0 + for _, s := range all { + if maxLen < len(s) { + maxLen = len(s) + } + fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) + } + fmt.Fprintln(&buf, ")\n") + + fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) + fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) + + fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) + for i, s := range best.tab { + if s == "" { + continue + } + fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) + } + fmt.Fprintf(&buf, "}\n") + datasize := (1 << best.k) * 4 + + fmt.Fprintln(&buf, "const atomText =") + textsize := len(text) + for len(text) > 60 { + fmt.Fprintf(&buf, "\t%q +\n", text[:60]) + text = text[60:] + } + fmt.Fprintf(&buf, "\t%q\n\n", text) + + genFile("table.go", &buf) + + fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) +} + +type byLen []string + +func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } +func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x byLen) Len() int { return len(x) } + +// fnv computes the FNV hash with an arbitrary starting value h. +func fnv(h uint32, s string) uint32 { + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// A table represents an attempt at constructing the lookup table. +// The lookup table uses cuckoo hashing, meaning that each string +// can be found in one of two positions. +type table struct { + h0 uint32 + k uint + mask uint32 + tab []string +} + +// hash returns the two hashes for s. +func (t *table) hash(s string) (h1, h2 uint32) { + h := fnv(t.h0, s) + h1 = h & t.mask + h2 = (h >> 16) & t.mask + return +} + +// init initializes the table with the given parameters. +// h0 is the initial hash value, +// k is the number of bits of hash value to use, and +// x is the list of strings to store in the table. +// init returns false if the table cannot be constructed. +func (t *table) init(h0 uint32, k uint, x []string) bool { + t.h0 = h0 + t.k = k + t.tab = make([]string, 1< len(t.tab) { + return false + } + s := t.tab[i] + h1, h2 := t.hash(s) + j := h1 + h2 - i + if t.tab[j] != "" && !t.push(j, depth+1) { + return false + } + t.tab[j] = s + return true +} + +// The lists of element names and attribute keys were taken from +// https://html.spec.whatwg.org/multipage/indices.html#index +// as of the "HTML Living Standard - Last Updated 16 April 2018" version. + +// "command", "keygen" and "menuitem" have been removed from the spec, +// but are kept here for backwards compatibility. +var elements = []string{ + "a", + "abbr", + "address", + "area", + "article", + "aside", + "audio", + "b", + "base", + "bdi", + "bdo", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "cite", + "code", + "col", + "colgroup", + "command", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "main", + "map", + "mark", + "menu", + "menuitem", + "meta", + "meter", + "nav", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "picture", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "slot", + "small", + "source", + "span", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "u", + "ul", + "var", + "video", + "wbr", +} + +// https://html.spec.whatwg.org/multipage/indices.html#attributes-3 +// +// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", +// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, +// but are kept here for backwards compatibility. +var attributes = []string{ + "abbr", + "accept", + "accept-charset", + "accesskey", + "action", + "allowfullscreen", + "allowpaymentrequest", + "allowusermedia", + "alt", + "as", + "async", + "autocomplete", + "autofocus", + "autoplay", + "challenge", + "charset", + "checked", + "cite", + "class", + "color", + "cols", + "colspan", + "command", + "content", + "contenteditable", + "contextmenu", + "controls", + "coords", + "crossorigin", + "data", + "datetime", + "default", + "defer", + "dir", + "dirname", + "disabled", + "download", + "draggable", + "dropzone", + "enctype", + "for", + "form", + "formaction", + "formenctype", + "formmethod", + "formnovalidate", + "formtarget", + "headers", + "height", + "hidden", + "high", + "href", + "hreflang", + "http-equiv", + "icon", + "id", + "inputmode", + "integrity", + "is", + "ismap", + "itemid", + "itemprop", + "itemref", + "itemscope", + "itemtype", + "keytype", + "kind", + "label", + "lang", + "list", + "loop", + "low", + "manifest", + "max", + "maxlength", + "media", + "mediagroup", + "method", + "min", + "minlength", + "multiple", + "muted", + "name", + "nomodule", + "nonce", + "novalidate", + "open", + "optimum", + "pattern", + "ping", + "placeholder", + "playsinline", + "poster", + "preload", + "radiogroup", + "readonly", + "referrerpolicy", + "rel", + "required", + "reversed", + "rows", + "rowspan", + "sandbox", + "spellcheck", + "scope", + "scoped", + "seamless", + "selected", + "shape", + "size", + "sizes", + "sortable", + "sorted", + "slot", + "span", + "spellcheck", + "src", + "srcdoc", + "srclang", + "srcset", + "start", + "step", + "style", + "tabindex", + "target", + "title", + "translate", + "type", + "typemustmatch", + "updateviacache", + "usemap", + "value", + "width", + "workertype", + "wrap", +} + +// "onautocomplete", "onautocompleteerror", "onmousewheel", +// "onshow" and "onsort" have been removed from the spec, +// but are kept here for backwards compatibility. +var eventHandlers = []string{ + "onabort", + "onautocomplete", + "onautocompleteerror", + "onauxclick", + "onafterprint", + "onbeforeprint", + "onbeforeunload", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncopy", + "oncuechange", + "oncut", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragexit", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "onhashchange", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onlanguagechange", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadend", + "onloadstart", + "onmessage", + "onmessageerror", + "onmousedown", + "onmouseenter", + "onmouseleave", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onwheel", + "onoffline", + "ononline", + "onpagehide", + "onpageshow", + "onpaste", + "onpause", + "onplay", + "onplaying", + "onpopstate", + "onprogress", + "onratechange", + "onreset", + "onresize", + "onrejectionhandled", + "onscroll", + "onsecuritypolicyviolation", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onsort", + "onstalled", + "onstorage", + "onsubmit", + "onsuspend", + "ontimeupdate", + "ontoggle", + "onunhandledrejection", + "onunload", + "onvolumechange", + "onwaiting", +} + +// extra are ad-hoc values not covered by any of the lists above. +var extra = []string{ + "acronym", + "align", + "annotation", + "annotation-xml", + "applet", + "basefont", + "bgsound", + "big", + "blink", + "center", + "color", + "desc", + "face", + "font", + "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. + "foreignobject", + "frame", + "frameset", + "image", + "isindex", + "listing", + "malignmark", + "marquee", + "math", + "mglyph", + "mi", + "mn", + "mo", + "ms", + "mtext", + "nobr", + "noembed", + "noframes", + "plaintext", + "prompt", + "public", + "rb", + "rtc", + "spacer", + "strike", + "svg", + "system", + "tt", + "xmp", +} diff --git a/vendor/golang.org/x/net/internal/iana/gen.go b/vendor/golang.org/x/net/internal/iana/gen.go new file mode 100644 index 000000000..2a7661c27 --- /dev/null +++ b/vendor/golang.org/x/net/internal/iana/gen.go @@ -0,0 +1,383 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +//go:generate go run gen.go + +// This program generates internet protocol constants and tables by +// reading IANA protocol registries. +package main + +import ( + "bytes" + "encoding/xml" + "fmt" + "go/format" + "io" + "io/ioutil" + "net/http" + "os" + "strconv" + "strings" +) + +var registries = []struct { + url string + parse func(io.Writer, io.Reader) error +}{ + { + "https://www.iana.org/assignments/dscp-registry/dscp-registry.xml", + parseDSCPRegistry, + }, + { + "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml", + parseProtocolNumbers, + }, + { + "https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml", + parseAddrFamilyNumbers, + }, +} + +func main() { + var bb bytes.Buffer + fmt.Fprintf(&bb, "// go generate gen.go\n") + fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") + fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n") + fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n") + for _, r := range registries { + resp, err := http.Get(r.url) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url) + os.Exit(1) + } + if err := r.parse(&bb, resp.Body); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Fprintf(&bb, "\n") + } + b, err := format.Source(bb.Bytes()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := ioutil.WriteFile("const.go", b, 0644); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func parseDSCPRegistry(w io.Writer, r io.Reader) error { + dec := xml.NewDecoder(r) + var dr dscpRegistry + if err := dec.Decode(&dr); err != nil { + return err + } + fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated) + fmt.Fprintf(w, "const (\n") + for _, dr := range dr.escapeDSCP() { + fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value) + fmt.Fprintf(w, "// %s\n", dr.OrigName) + } + for _, er := range dr.escapeECN() { + fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value) + fmt.Fprintf(w, "// %s\n", er.OrigDescr) + } + fmt.Fprintf(w, ")\n") + return nil +} + +type dscpRegistry struct { + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + Note string `xml:"note"` + Registries []struct { + Title string `xml:"title"` + Registries []struct { + Title string `xml:"title"` + Records []struct { + Name string `xml:"name"` + Space string `xml:"space"` + } `xml:"record"` + } `xml:"registry"` + Records []struct { + Value string `xml:"value"` + Descr string `xml:"description"` + } `xml:"record"` + } `xml:"registry"` +} + +type canonDSCPRecord struct { + OrigName string + Name string + Value int +} + +func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord { + var drs []canonDSCPRecord + for _, preg := range drr.Registries { + if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") { + continue + } + for _, reg := range preg.Registries { + if !strings.Contains(reg.Title, "Pool 1 Codepoints") { + continue + } + drs = make([]canonDSCPRecord, len(reg.Records)) + sr := strings.NewReplacer( + "+", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, dr := range reg.Records { + s := strings.TrimSpace(dr.Name) + drs[i].OrigName = s + drs[i].Name = sr.Replace(s) + n, err := strconv.ParseUint(dr.Space, 2, 8) + if err != nil { + continue + } + drs[i].Value = int(n) << 2 + } + } + } + return drs +} + +type canonECNRecord struct { + OrigDescr string + Descr string + Value int +} + +func (drr *dscpRegistry) escapeECN() []canonECNRecord { + var ers []canonECNRecord + for _, reg := range drr.Registries { + if !strings.Contains(reg.Title, "ECN Field") { + continue + } + ers = make([]canonECNRecord, len(reg.Records)) + sr := strings.NewReplacer( + "Capable", "", + "Not-ECT", "", + "ECT(1)", "", + "ECT(0)", "", + "CE", "", + "(", "", + ")", "", + "+", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, er := range reg.Records { + s := strings.TrimSpace(er.Descr) + ers[i].OrigDescr = s + ss := strings.Split(s, " ") + if len(ss) > 1 { + ers[i].Descr = strings.Join(ss[1:], " ") + } else { + ers[i].Descr = ss[0] + } + ers[i].Descr = sr.Replace(er.Descr) + n, err := strconv.ParseUint(er.Value, 2, 8) + if err != nil { + continue + } + ers[i].Value = int(n) + } + } + return ers +} + +func parseProtocolNumbers(w io.Writer, r io.Reader) error { + dec := xml.NewDecoder(r) + var pn protocolNumbers + if err := dec.Decode(&pn); err != nil { + return err + } + prs := pn.escape() + prs = append([]canonProtocolRecord{{ + Name: "IP", + Descr: "IPv4 encapsulation, pseudo protocol number", + Value: 0, + }}, prs...) + fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated) + fmt.Fprintf(w, "const (\n") + for _, pr := range prs { + if pr.Name == "" { + continue + } + fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value) + s := pr.Descr + if s == "" { + s = pr.OrigName + } + fmt.Fprintf(w, "// %s\n", s) + } + fmt.Fprintf(w, ")\n") + return nil +} + +type protocolNumbers struct { + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + RegTitle string `xml:"registry>title"` + Note string `xml:"registry>note"` + Records []struct { + Value string `xml:"value"` + Name string `xml:"name"` + Descr string `xml:"description"` + } `xml:"registry>record"` +} + +type canonProtocolRecord struct { + OrigName string + Name string + Descr string + Value int +} + +func (pn *protocolNumbers) escape() []canonProtocolRecord { + prs := make([]canonProtocolRecord, len(pn.Records)) + sr := strings.NewReplacer( + "-in-", "in", + "-within-", "within", + "-over-", "over", + "+", "P", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, pr := range pn.Records { + if strings.Contains(pr.Name, "Deprecated") || + strings.Contains(pr.Name, "deprecated") { + continue + } + prs[i].OrigName = pr.Name + s := strings.TrimSpace(pr.Name) + switch pr.Name { + case "ISIS over IPv4": + prs[i].Name = "ISIS" + case "manet": + prs[i].Name = "MANET" + default: + prs[i].Name = sr.Replace(s) + } + ss := strings.Split(pr.Descr, "\n") + for i := range ss { + ss[i] = strings.TrimSpace(ss[i]) + } + if len(ss) > 1 { + prs[i].Descr = strings.Join(ss, " ") + } else { + prs[i].Descr = ss[0] + } + prs[i].Value, _ = strconv.Atoi(pr.Value) + } + return prs +} + +func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error { + dec := xml.NewDecoder(r) + var afn addrFamilylNumbers + if err := dec.Decode(&afn); err != nil { + return err + } + afrs := afn.escape() + fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated) + fmt.Fprintf(w, "const (\n") + for _, afr := range afrs { + if afr.Name == "" { + continue + } + fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value) + fmt.Fprintf(w, "// %s\n", afr.Descr) + } + fmt.Fprintf(w, ")\n") + return nil +} + +type addrFamilylNumbers struct { + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + RegTitle string `xml:"registry>title"` + Note string `xml:"registry>note"` + Records []struct { + Value string `xml:"value"` + Descr string `xml:"description"` + } `xml:"registry>record"` +} + +type canonAddrFamilyRecord struct { + Name string + Descr string + Value int +} + +func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord { + afrs := make([]canonAddrFamilyRecord, len(afn.Records)) + sr := strings.NewReplacer( + "IP version 4", "IPv4", + "IP version 6", "IPv6", + "Identifier", "ID", + "-", "", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, afr := range afn.Records { + if strings.Contains(afr.Descr, "Unassigned") || + strings.Contains(afr.Descr, "Reserved") { + continue + } + afrs[i].Descr = afr.Descr + s := strings.TrimSpace(afr.Descr) + switch s { + case "IP (IP version 4)": + afrs[i].Name = "IPv4" + case "IP6 (IP version 6)": + afrs[i].Name = "IPv6" + case "AFI for L2VPN information": + afrs[i].Name = "L2VPN" + case "E.164 with NSAP format subaddress": + afrs[i].Name = "E164withSubaddress" + case "MT IP: Multi-Topology IP version 4": + afrs[i].Name = "MTIPv4" + case "MAC/24": + afrs[i].Name = "MACFinal24bits" + case "MAC/40": + afrs[i].Name = "MACFinal40bits" + case "IPv6/64": + afrs[i].Name = "IPv6Initial64bits" + default: + n := strings.Index(s, "(") + if n > 0 { + s = s[:n] + } + n = strings.Index(s, ":") + if n > 0 { + s = s[:n] + } + afrs[i].Name = sr.Replace(s) + } + afrs[i].Value, _ = strconv.Atoi(afr.Value) + } + return afrs +} diff --git a/vendor/golang.org/x/net/internal/socket/defs_aix.go b/vendor/golang.org/x/net/internal/socket/defs_aix.go new file mode 100644 index 000000000..ae1b21c5e --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_aix.go @@ -0,0 +1,38 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type mmsghdr C.struct_mmsghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_darwin.go b/vendor/golang.org/x/net/internal/socket/defs_darwin.go new file mode 100644 index 000000000..b780bc67a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_darwin.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go b/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go new file mode 100644 index 000000000..b780bc67a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_dragonfly.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_freebsd.go b/vendor/golang.org/x/net/internal/socket/defs_freebsd.go new file mode 100644 index 000000000..b780bc67a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_freebsd.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_linux.go b/vendor/golang.org/x/net/internal/socket/defs_linux.go new file mode 100644 index 000000000..85bb7450b --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_linux.go @@ -0,0 +1,40 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include +#include + +#define _GNU_SOURCE +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type mmsghdr C.struct_mmsghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_netbsd.go b/vendor/golang.org/x/net/internal/socket/defs_netbsd.go new file mode 100644 index 000000000..5bfdd4676 --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_netbsd.go @@ -0,0 +1,38 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type mmsghdr C.struct_mmsghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_openbsd.go b/vendor/golang.org/x/net/internal/socket/defs_openbsd.go new file mode 100644 index 000000000..b780bc67a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_openbsd.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/defs_solaris.go b/vendor/golang.org/x/net/internal/socket/defs_solaris.go new file mode 100644 index 000000000..b780bc67a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socket/defs_solaris.go @@ -0,0 +1,36 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package socket + +/* +#include + +#include +*/ +import "C" + +type iovec C.struct_iovec + +type msghdr C.struct_msghdr + +type cmsghdr C.struct_cmsghdr + +type sockaddrInet C.struct_sockaddr_in + +type sockaddrInet6 C.struct_sockaddr_in6 + +const ( + sizeofIovec = C.sizeof_struct_iovec + sizeofMsghdr = C.sizeof_struct_msghdr + sizeofCmsghdr = C.sizeof_struct_cmsghdr + + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 +) diff --git a/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go b/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go index 813385a98..e740c8f02 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go @@ -53,7 +53,6 @@ type sockaddrInet6 struct { const ( sizeofIovec = 0x10 sizeofMsghdr = 0x30 - sizeofMmsghdr = 0x38 sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go index 72d8b2542..d33025b70 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_386.go @@ -47,7 +47,6 @@ type sockaddrInet6 struct { const ( sizeofIovec = 0x8 sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go index 3545319ae..b20d21677 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go @@ -50,7 +50,6 @@ type sockaddrInet6 struct { const ( sizeofIovec = 0x10 sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go index 72d8b2542..1bb10a428 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go @@ -45,9 +45,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x8 - sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 + sizeofIovec = 0x8 + sizeofMsghdr = 0x1c + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go index 72d8b2542..1bb10a428 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go @@ -45,9 +45,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x8 - sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 + sizeofIovec = 0x8 + sizeofMsghdr = 0x1c + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go index 72d8b2542..1bb10a428 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go @@ -45,9 +45,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x8 - sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 + sizeofIovec = 0x8 + sizeofMsghdr = 0x1c + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go index dbff234fb..f12a1d768 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go @@ -49,9 +49,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go b/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go index 3545319ae..7f6e8a7fa 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go @@ -48,9 +48,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x38 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x38 + sizeofCmsghdr = 0x10 sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go index bf8f47c88..7e258cec2 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go @@ -47,9 +47,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x8 - sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 + sizeofIovec = 0x8 + sizeofMsghdr = 0x1c + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go index a46eff991..b3f9c0d7e 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go @@ -50,9 +50,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x30 - sizeofMmsghdr = 0x40 + sizeofIovec = 0x10 + sizeofMsghdr = 0x30 + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go index bf8f47c88..7e258cec2 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go @@ -47,9 +47,9 @@ type sockaddrInet6 struct { } const ( - sizeofIovec = 0x8 - sizeofMsghdr = 0x1c - sizeofMmsghdr = 0x20 + sizeofIovec = 0x8 + sizeofMsghdr = 0x1c + sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go index a46eff991..da26ef019 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go @@ -52,7 +52,6 @@ type sockaddrInet6 struct { const ( sizeofIovec = 0x10 sizeofMsghdr = 0x30 - sizeofMmsghdr = 0x40 sizeofCmsghdr = 0xc sizeofSockaddrInet = 0x10 diff --git a/vendor/golang.org/x/net/ipv4/defs_aix.go b/vendor/golang.org/x/net/ipv4/defs_aix.go new file mode 100644 index 000000000..0f37211c6 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_aix.go @@ -0,0 +1,39 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + // IP_RECVIF is defined on AIX but doesn't work. + // IP_RECVINTERFACE must be used instead. + sysIP_RECVIF = C.IP_RECVINTERFACE + sysIP_RECVTTL = C.IP_RECVTTL + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + + sizeofIPMreq = C.sizeof_struct_ip_mreq +) + +type ipMreq C.struct_ip_mreq diff --git a/vendor/golang.org/x/net/ipv4/defs_darwin.go b/vendor/golang.org/x/net/ipv4/defs_darwin.go new file mode 100644 index 000000000..c8f2e05b8 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_darwin.go @@ -0,0 +1,77 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include + +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_STRIPHDR = C.IP_STRIPHDR + sysIP_RECVTTL = C.IP_RECVTTL + sysIP_BOUND_IF = C.IP_BOUND_IF + sysIP_PKTINFO = C.IP_PKTINFO + sysIP_RECVPKTINFO = C.IP_RECVPKTINFO + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF + sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX + sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP + sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP + sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE + sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE + sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP + sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP + sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP + sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP + sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE + sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE + + sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofInetPktinfo = C.sizeof_struct_in_pktinfo + + sizeofIPMreq = C.sizeof_struct_ip_mreq + sizeofIPMreqn = C.sizeof_struct_ip_mreqn + sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source + sizeofGroupReq = C.sizeof_struct_group_req + sizeofGroupSourceReq = C.sizeof_struct_group_source_req +) + +type sockaddrStorage C.struct_sockaddr_storage + +type sockaddrInet C.struct_sockaddr_in + +type inetPktinfo C.struct_in_pktinfo + +type ipMreq C.struct_ip_mreq + +type ipMreqn C.struct_ip_mreqn + +type ipMreqSource C.struct_ip_mreq_source + +type groupReq C.struct_group_req + +type groupSourceReq C.struct_group_source_req diff --git a/vendor/golang.org/x/net/ipv4/defs_dragonfly.go b/vendor/golang.org/x/net/ipv4/defs_dragonfly.go new file mode 100644 index 000000000..f30544ea2 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_dragonfly.go @@ -0,0 +1,38 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_RECVTTL = C.IP_RECVTTL + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + + sizeofIPMreq = C.sizeof_struct_ip_mreq +) + +type ipMreq C.struct_ip_mreq diff --git a/vendor/golang.org/x/net/ipv4/defs_freebsd.go b/vendor/golang.org/x/net/ipv4/defs_freebsd.go new file mode 100644 index 000000000..4dd57d865 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_freebsd.go @@ -0,0 +1,75 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include + +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_SENDSRCADDR = C.IP_SENDSRCADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_ONESBCAST = C.IP_ONESBCAST + sysIP_BINDANY = C.IP_BINDANY + sysIP_RECVTTL = C.IP_RECVTTL + sysIP_MINTTL = C.IP_MINTTL + sysIP_DONTFRAG = C.IP_DONTFRAG + sysIP_RECVTOS = C.IP_RECVTOS + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF + sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP + sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP + sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE + sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE + sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP + sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP + sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP + sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP + sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE + sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE + + sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + + sizeofIPMreq = C.sizeof_struct_ip_mreq + sizeofIPMreqn = C.sizeof_struct_ip_mreqn + sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source + sizeofGroupReq = C.sizeof_struct_group_req + sizeofGroupSourceReq = C.sizeof_struct_group_source_req +) + +type sockaddrStorage C.struct_sockaddr_storage + +type sockaddrInet C.struct_sockaddr_in + +type ipMreq C.struct_ip_mreq + +type ipMreqn C.struct_ip_mreqn + +type ipMreqSource C.struct_ip_mreq_source + +type groupReq C.struct_group_req + +type groupSourceReq C.struct_group_source_req diff --git a/vendor/golang.org/x/net/ipv4/defs_linux.go b/vendor/golang.org/x/net/ipv4/defs_linux.go new file mode 100644 index 000000000..beb11071a --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_linux.go @@ -0,0 +1,122 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include + +#include +#include +#include +#include +#include +*/ +import "C" + +const ( + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_PKTINFO = C.IP_PKTINFO + sysIP_PKTOPTIONS = C.IP_PKTOPTIONS + sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER + sysIP_RECVERR = C.IP_RECVERR + sysIP_RECVTTL = C.IP_RECVTTL + sysIP_RECVTOS = C.IP_RECVTOS + sysIP_MTU = C.IP_MTU + sysIP_FREEBIND = C.IP_FREEBIND + sysIP_TRANSPARENT = C.IP_TRANSPARENT + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR + sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR + sysIP_MINTTL = C.IP_MINTTL + sysIP_NODEFRAG = C.IP_NODEFRAG + sysIP_UNICAST_IF = C.IP_UNICAST_IF + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE + sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE + sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP + sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP + sysIP_MSFILTER = C.IP_MSFILTER + sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP + sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP + sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP + sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP + sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE + sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE + sysMCAST_MSFILTER = C.MCAST_MSFILTER + sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL + + //sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT + //sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT + //sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO + //sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE + //sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE + //sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT + + sysICMP_FILTER = C.ICMP_FILTER + + sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE + sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL + sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP + sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6 + sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS + sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING + + sysSOL_SOCKET = C.SOL_SOCKET + sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER + + sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofInetPktinfo = C.sizeof_struct_in_pktinfo + sizeofSockExtendedErr = C.sizeof_struct_sock_extended_err + + sizeofIPMreq = C.sizeof_struct_ip_mreq + sizeofIPMreqn = C.sizeof_struct_ip_mreqn + sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source + sizeofGroupReq = C.sizeof_struct_group_req + sizeofGroupSourceReq = C.sizeof_struct_group_source_req + + sizeofICMPFilter = C.sizeof_struct_icmp_filter + + sizeofSockFprog = C.sizeof_struct_sock_fprog +) + +type kernelSockaddrStorage C.struct___kernel_sockaddr_storage + +type sockaddrInet C.struct_sockaddr_in + +type inetPktinfo C.struct_in_pktinfo + +type sockExtendedErr C.struct_sock_extended_err + +type ipMreq C.struct_ip_mreq + +type ipMreqn C.struct_ip_mreqn + +type ipMreqSource C.struct_ip_mreq_source + +type groupReq C.struct_group_req + +type groupSourceReq C.struct_group_source_req + +type icmpFilter C.struct_icmp_filter + +type sockFProg C.struct_sock_fprog + +type sockFilter C.struct_sock_filter diff --git a/vendor/golang.org/x/net/ipv4/defs_netbsd.go b/vendor/golang.org/x/net/ipv4/defs_netbsd.go new file mode 100644 index 000000000..8f8af1b89 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_netbsd.go @@ -0,0 +1,37 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_RECVTTL = C.IP_RECVTTL + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + + sizeofIPMreq = C.sizeof_struct_ip_mreq +) + +type ipMreq C.struct_ip_mreq diff --git a/vendor/golang.org/x/net/ipv4/defs_openbsd.go b/vendor/golang.org/x/net/ipv4/defs_openbsd.go new file mode 100644 index 000000000..8f8af1b89 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_openbsd.go @@ -0,0 +1,37 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_RECVTTL = C.IP_RECVTTL + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + + sizeofIPMreq = C.sizeof_struct_ip_mreq +) + +type ipMreq C.struct_ip_mreq diff --git a/vendor/golang.org/x/net/ipv4/defs_solaris.go b/vendor/golang.org/x/net/ipv4/defs_solaris.go new file mode 100644 index 000000000..aeb33e9c8 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/defs_solaris.go @@ -0,0 +1,84 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// +godefs map struct_in_addr [4]byte /* in_addr */ + +package ipv4 + +/* +#include + +#include +*/ +import "C" + +const ( + sysIP_OPTIONS = C.IP_OPTIONS + sysIP_HDRINCL = C.IP_HDRINCL + sysIP_TOS = C.IP_TOS + sysIP_TTL = C.IP_TTL + sysIP_RECVOPTS = C.IP_RECVOPTS + sysIP_RECVRETOPTS = C.IP_RECVRETOPTS + sysIP_RECVDSTADDR = C.IP_RECVDSTADDR + sysIP_RETOPTS = C.IP_RETOPTS + sysIP_RECVIF = C.IP_RECVIF + sysIP_RECVSLLA = C.IP_RECVSLLA + sysIP_RECVTTL = C.IP_RECVTTL + + sysIP_MULTICAST_IF = C.IP_MULTICAST_IF + sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL + sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP + sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP + sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP + sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE + sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE + sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP + sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP + sysIP_NEXTHOP = C.IP_NEXTHOP + + sysIP_PKTINFO = C.IP_PKTINFO + sysIP_RECVPKTINFO = C.IP_RECVPKTINFO + sysIP_DONTFRAG = C.IP_DONTFRAG + + sysIP_BOUND_IF = C.IP_BOUND_IF + sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC + sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL + sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF + + sysIP_REUSEADDR = C.IP_REUSEADDR + sysIP_DONTROUTE = C.IP_DONTROUTE + sysIP_BROADCAST = C.IP_BROADCAST + + sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP + sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP + sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE + sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE + sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP + sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP + + sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage + sizeofSockaddrInet = C.sizeof_struct_sockaddr_in + sizeofInetPktinfo = C.sizeof_struct_in_pktinfo + + sizeofIPMreq = C.sizeof_struct_ip_mreq + sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source + sizeofGroupReq = C.sizeof_struct_group_req + sizeofGroupSourceReq = C.sizeof_struct_group_source_req +) + +type sockaddrStorage C.struct_sockaddr_storage + +type sockaddrInet C.struct_sockaddr_in + +type inetPktinfo C.struct_in_pktinfo + +type ipMreq C.struct_ip_mreq + +type ipMreqSource C.struct_ip_mreq_source + +type groupReq C.struct_group_req + +type groupSourceReq C.struct_group_source_req diff --git a/vendor/golang.org/x/net/ipv4/gen.go b/vendor/golang.org/x/net/ipv4/gen.go new file mode 100644 index 000000000..1bb1737f6 --- /dev/null +++ b/vendor/golang.org/x/net/ipv4/gen.go @@ -0,0 +1,199 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +//go:generate go run gen.go + +// This program generates system adaptation constants and types, +// internet protocol constants and tables by reading template files +// and IANA protocol registries. +package main + +import ( + "bytes" + "encoding/xml" + "fmt" + "go/format" + "io" + "io/ioutil" + "net/http" + "os" + "os/exec" + "runtime" + "strconv" + "strings" +) + +func main() { + if err := genzsys(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := geniana(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func genzsys() error { + defs := "defs_" + runtime.GOOS + ".go" + f, err := os.Open(defs) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + f.Close() + cmd := exec.Command("go", "tool", "cgo", "-godefs", defs) + b, err := cmd.Output() + if err != nil { + return err + } + b, err = format.Source(b) + if err != nil { + return err + } + zsys := "zsys_" + runtime.GOOS + ".go" + switch runtime.GOOS { + case "freebsd", "linux": + zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go" + } + if err := ioutil.WriteFile(zsys, b, 0644); err != nil { + return err + } + return nil +} + +var registries = []struct { + url string + parse func(io.Writer, io.Reader) error +}{ + { + "https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml", + parseICMPv4Parameters, + }, +} + +func geniana() error { + var bb bytes.Buffer + fmt.Fprintf(&bb, "// go generate gen.go\n") + fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") + fmt.Fprintf(&bb, "package ipv4\n\n") + for _, r := range registries { + resp, err := http.Get(r.url) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url) + } + if err := r.parse(&bb, resp.Body); err != nil { + return err + } + fmt.Fprintf(&bb, "\n") + } + b, err := format.Source(bb.Bytes()) + if err != nil { + return err + } + if err := ioutil.WriteFile("iana.go", b, 0644); err != nil { + return err + } + return nil +} + +func parseICMPv4Parameters(w io.Writer, r io.Reader) error { + dec := xml.NewDecoder(r) + var icp icmpv4Parameters + if err := dec.Decode(&icp); err != nil { + return err + } + prs := icp.escape() + fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated) + fmt.Fprintf(w, "const (\n") + for _, pr := range prs { + if pr.Descr == "" { + continue + } + fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value) + fmt.Fprintf(w, "// %s\n", pr.OrigDescr) + } + fmt.Fprintf(w, ")\n\n") + fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated) + fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n") + for _, pr := range prs { + if pr.Descr == "" { + continue + } + fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr)) + } + fmt.Fprintf(w, "}\n") + return nil +} + +type icmpv4Parameters struct { + XMLName xml.Name `xml:"registry"` + Title string `xml:"title"` + Updated string `xml:"updated"` + Registries []struct { + Title string `xml:"title"` + Records []struct { + Value string `xml:"value"` + Descr string `xml:"description"` + } `xml:"record"` + } `xml:"registry"` +} + +type canonICMPv4ParamRecord struct { + OrigDescr string + Descr string + Value int +} + +func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord { + id := -1 + for i, r := range icp.Registries { + if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") { + id = i + break + } + } + if id < 0 { + return nil + } + prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records)) + sr := strings.NewReplacer( + "Messages", "", + "Message", "", + "ICMP", "", + "+", "P", + "-", "", + "/", "", + ".", "", + " ", "", + ) + for i, pr := range icp.Registries[id].Records { + if strings.Contains(pr.Descr, "Reserved") || + strings.Contains(pr.Descr, "Unassigned") || + strings.Contains(pr.Descr, "Deprecated") || + strings.Contains(pr.Descr, "Experiment") || + strings.Contains(pr.Descr, "experiment") { + continue + } + ss := strings.Split(pr.Descr, "\n") + if len(ss) > 1 { + prs[i].Descr = strings.Join(ss, " ") + } else { + prs[i].Descr = ss[0] + } + s := strings.TrimSpace(prs[i].Descr) + prs[i].OrigDescr = s + prs[i].Descr = sr.Replace(s) + prs[i].Value, _ = strconv.Atoi(pr.Value) + } + return prs +} diff --git a/vendor/golang.org/x/net/websocket/client.go b/vendor/golang.org/x/net/websocket/client.go deleted file mode 100644 index 69a4ac7ee..000000000 --- a/vendor/golang.org/x/net/websocket/client.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package websocket - -import ( - "bufio" - "io" - "net" - "net/http" - "net/url" -) - -// DialError is an error that occurs while dialling a websocket server. -type DialError struct { - *Config - Err error -} - -func (e *DialError) Error() string { - return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error() -} - -// NewConfig creates a new WebSocket config for client connection. -func NewConfig(server, origin string) (config *Config, err error) { - config = new(Config) - config.Version = ProtocolVersionHybi13 - config.Location, err = url.ParseRequestURI(server) - if err != nil { - return - } - config.Origin, err = url.ParseRequestURI(origin) - if err != nil { - return - } - config.Header = http.Header(make(map[string][]string)) - return -} - -// NewClient creates a new WebSocket client connection over rwc. -func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { - br := bufio.NewReader(rwc) - bw := bufio.NewWriter(rwc) - err = hybiClientHandshake(config, br, bw) - if err != nil { - return - } - buf := bufio.NewReadWriter(br, bw) - ws = newHybiClientConn(config, buf, rwc) - return -} - -// Dial opens a new client connection to a WebSocket. -func Dial(url_, protocol, origin string) (ws *Conn, err error) { - config, err := NewConfig(url_, origin) - if err != nil { - return nil, err - } - if protocol != "" { - config.Protocol = []string{protocol} - } - return DialConfig(config) -} - -var portMap = map[string]string{ - "ws": "80", - "wss": "443", -} - -func parseAuthority(location *url.URL) string { - if _, ok := portMap[location.Scheme]; ok { - if _, _, err := net.SplitHostPort(location.Host); err != nil { - return net.JoinHostPort(location.Host, portMap[location.Scheme]) - } - } - return location.Host -} - -// DialConfig opens a new client connection to a WebSocket with a config. -func DialConfig(config *Config) (ws *Conn, err error) { - var client net.Conn - if config.Location == nil { - return nil, &DialError{config, ErrBadWebSocketLocation} - } - if config.Origin == nil { - return nil, &DialError{config, ErrBadWebSocketOrigin} - } - dialer := config.Dialer - if dialer == nil { - dialer = &net.Dialer{} - } - client, err = dialWithDialer(dialer, config) - if err != nil { - goto Error - } - ws, err = NewClient(config, client) - if err != nil { - client.Close() - goto Error - } - return - -Error: - return nil, &DialError{config, err} -} diff --git a/vendor/golang.org/x/net/websocket/dial.go b/vendor/golang.org/x/net/websocket/dial.go deleted file mode 100644 index 2dab943a4..000000000 --- a/vendor/golang.org/x/net/websocket/dial.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package websocket - -import ( - "crypto/tls" - "net" -) - -func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) { - switch config.Location.Scheme { - case "ws": - conn, err = dialer.Dial("tcp", parseAuthority(config.Location)) - - case "wss": - conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig) - - default: - err = ErrBadScheme - } - return -} diff --git a/vendor/golang.org/x/net/websocket/hybi.go b/vendor/golang.org/x/net/websocket/hybi.go deleted file mode 100644 index 8cffdd16c..000000000 --- a/vendor/golang.org/x/net/websocket/hybi.go +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package websocket - -// This file implements a protocol of hybi draft. -// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 - -import ( - "bufio" - "bytes" - "crypto/rand" - "crypto/sha1" - "encoding/base64" - "encoding/binary" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -const ( - websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" - - closeStatusNormal = 1000 - closeStatusGoingAway = 1001 - closeStatusProtocolError = 1002 - closeStatusUnsupportedData = 1003 - closeStatusFrameTooLarge = 1004 - closeStatusNoStatusRcvd = 1005 - closeStatusAbnormalClosure = 1006 - closeStatusBadMessageData = 1007 - closeStatusPolicyViolation = 1008 - closeStatusTooBigData = 1009 - closeStatusExtensionMismatch = 1010 - - maxControlFramePayloadLength = 125 -) - -var ( - ErrBadMaskingKey = &ProtocolError{"bad masking key"} - ErrBadPongMessage = &ProtocolError{"bad pong message"} - ErrBadClosingStatus = &ProtocolError{"bad closing status"} - ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"} - ErrNotImplemented = &ProtocolError{"not implemented"} - - handshakeHeader = map[string]bool{ - "Host": true, - "Upgrade": true, - "Connection": true, - "Sec-Websocket-Key": true, - "Sec-Websocket-Origin": true, - "Sec-Websocket-Version": true, - "Sec-Websocket-Protocol": true, - "Sec-Websocket-Accept": true, - } -) - -// A hybiFrameHeader is a frame header as defined in hybi draft. -type hybiFrameHeader struct { - Fin bool - Rsv [3]bool - OpCode byte - Length int64 - MaskingKey []byte - - data *bytes.Buffer -} - -// A hybiFrameReader is a reader for hybi frame. -type hybiFrameReader struct { - reader io.Reader - - header hybiFrameHeader - pos int64 - length int -} - -func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) { - n, err = frame.reader.Read(msg) - if frame.header.MaskingKey != nil { - for i := 0; i < n; i++ { - msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4] - frame.pos++ - } - } - return n, err -} - -func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode } - -func (frame *hybiFrameReader) HeaderReader() io.Reader { - if frame.header.data == nil { - return nil - } - if frame.header.data.Len() == 0 { - return nil - } - return frame.header.data -} - -func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil } - -func (frame *hybiFrameReader) Len() (n int) { return frame.length } - -// A hybiFrameReaderFactory creates new frame reader based on its frame type. -type hybiFrameReaderFactory struct { - *bufio.Reader -} - -// NewFrameReader reads a frame header from the connection, and creates new reader for the frame. -// See Section 5.2 Base Framing protocol for detail. -// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2 -func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) { - hybiFrame := new(hybiFrameReader) - frame = hybiFrame - var header []byte - var b byte - // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits) - b, err = buf.ReadByte() - if err != nil { - return - } - header = append(header, b) - hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0 - for i := 0; i < 3; i++ { - j := uint(6 - i) - hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0 - } - hybiFrame.header.OpCode = header[0] & 0x0f - - // Second byte. Mask/Payload len(7bits) - b, err = buf.ReadByte() - if err != nil { - return - } - header = append(header, b) - mask := (b & 0x80) != 0 - b &= 0x7f - lengthFields := 0 - switch { - case b <= 125: // Payload length 7bits. - hybiFrame.header.Length = int64(b) - case b == 126: // Payload length 7+16bits - lengthFields = 2 - case b == 127: // Payload length 7+64bits - lengthFields = 8 - } - for i := 0; i < lengthFields; i++ { - b, err = buf.ReadByte() - if err != nil { - return - } - if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits - b &= 0x7f - } - header = append(header, b) - hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b) - } - if mask { - // Masking key. 4 bytes. - for i := 0; i < 4; i++ { - b, err = buf.ReadByte() - if err != nil { - return - } - header = append(header, b) - hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b) - } - } - hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length) - hybiFrame.header.data = bytes.NewBuffer(header) - hybiFrame.length = len(header) + int(hybiFrame.header.Length) - return -} - -// A HybiFrameWriter is a writer for hybi frame. -type hybiFrameWriter struct { - writer *bufio.Writer - - header *hybiFrameHeader -} - -func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) { - var header []byte - var b byte - if frame.header.Fin { - b |= 0x80 - } - for i := 0; i < 3; i++ { - if frame.header.Rsv[i] { - j := uint(6 - i) - b |= 1 << j - } - } - b |= frame.header.OpCode - header = append(header, b) - if frame.header.MaskingKey != nil { - b = 0x80 - } else { - b = 0 - } - lengthFields := 0 - length := len(msg) - switch { - case length <= 125: - b |= byte(length) - case length < 65536: - b |= 126 - lengthFields = 2 - default: - b |= 127 - lengthFields = 8 - } - header = append(header, b) - for i := 0; i < lengthFields; i++ { - j := uint((lengthFields - i - 1) * 8) - b = byte((length >> j) & 0xff) - header = append(header, b) - } - if frame.header.MaskingKey != nil { - if len(frame.header.MaskingKey) != 4 { - return 0, ErrBadMaskingKey - } - header = append(header, frame.header.MaskingKey...) - frame.writer.Write(header) - data := make([]byte, length) - for i := range data { - data[i] = msg[i] ^ frame.header.MaskingKey[i%4] - } - frame.writer.Write(data) - err = frame.writer.Flush() - return length, err - } - frame.writer.Write(header) - frame.writer.Write(msg) - err = frame.writer.Flush() - return length, err -} - -func (frame *hybiFrameWriter) Close() error { return nil } - -type hybiFrameWriterFactory struct { - *bufio.Writer - needMaskingKey bool -} - -func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) { - frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType} - if buf.needMaskingKey { - frameHeader.MaskingKey, err = generateMaskingKey() - if err != nil { - return nil, err - } - } - return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil -} - -type hybiFrameHandler struct { - conn *Conn - payloadType byte -} - -func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) { - if handler.conn.IsServerConn() { - // The client MUST mask all frames sent to the server. - if frame.(*hybiFrameReader).header.MaskingKey == nil { - handler.WriteClose(closeStatusProtocolError) - return nil, io.EOF - } - } else { - // The server MUST NOT mask all frames. - if frame.(*hybiFrameReader).header.MaskingKey != nil { - handler.WriteClose(closeStatusProtocolError) - return nil, io.EOF - } - } - if header := frame.HeaderReader(); header != nil { - io.Copy(ioutil.Discard, header) - } - switch frame.PayloadType() { - case ContinuationFrame: - frame.(*hybiFrameReader).header.OpCode = handler.payloadType - case TextFrame, BinaryFrame: - handler.payloadType = frame.PayloadType() - case CloseFrame: - return nil, io.EOF - case PingFrame, PongFrame: - b := make([]byte, maxControlFramePayloadLength) - n, err := io.ReadFull(frame, b) - if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { - return nil, err - } - io.Copy(ioutil.Discard, frame) - if frame.PayloadType() == PingFrame { - if _, err := handler.WritePong(b[:n]); err != nil { - return nil, err - } - } - return nil, nil - } - return frame, nil -} - -func (handler *hybiFrameHandler) WriteClose(status int) (err error) { - handler.conn.wio.Lock() - defer handler.conn.wio.Unlock() - w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame) - if err != nil { - return err - } - msg := make([]byte, 2) - binary.BigEndian.PutUint16(msg, uint16(status)) - _, err = w.Write(msg) - w.Close() - return err -} - -func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) { - handler.conn.wio.Lock() - defer handler.conn.wio.Unlock() - w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame) - if err != nil { - return 0, err - } - n, err = w.Write(msg) - w.Close() - return n, err -} - -// newHybiConn creates a new WebSocket connection speaking hybi draft protocol. -func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn { - if buf == nil { - br := bufio.NewReader(rwc) - bw := bufio.NewWriter(rwc) - buf = bufio.NewReadWriter(br, bw) - } - ws := &Conn{config: config, request: request, buf: buf, rwc: rwc, - frameReaderFactory: hybiFrameReaderFactory{buf.Reader}, - frameWriterFactory: hybiFrameWriterFactory{ - buf.Writer, request == nil}, - PayloadType: TextFrame, - defaultCloseStatus: closeStatusNormal} - ws.frameHandler = &hybiFrameHandler{conn: ws} - return ws -} - -// generateMaskingKey generates a masking key for a frame. -func generateMaskingKey() (maskingKey []byte, err error) { - maskingKey = make([]byte, 4) - if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil { - return - } - return -} - -// generateNonce generates a nonce consisting of a randomly selected 16-byte -// value that has been base64-encoded. -func generateNonce() (nonce []byte) { - key := make([]byte, 16) - if _, err := io.ReadFull(rand.Reader, key); err != nil { - panic(err) - } - nonce = make([]byte, 24) - base64.StdEncoding.Encode(nonce, key) - return -} - -// removeZone removes IPv6 zone identifer from host. -// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080" -func removeZone(host string) string { - if !strings.HasPrefix(host, "[") { - return host - } - i := strings.LastIndex(host, "]") - if i < 0 { - return host - } - j := strings.LastIndex(host[:i], "%") - if j < 0 { - return host - } - return host[:j] + host[i:] -} - -// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of -// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string. -func getNonceAccept(nonce []byte) (expected []byte, err error) { - h := sha1.New() - if _, err = h.Write(nonce); err != nil { - return - } - if _, err = h.Write([]byte(websocketGUID)); err != nil { - return - } - expected = make([]byte, 28) - base64.StdEncoding.Encode(expected, h.Sum(nil)) - return -} - -// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17 -func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) { - bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n") - - // According to RFC 6874, an HTTP client, proxy, or other - // intermediary must remove any IPv6 zone identifier attached - // to an outgoing URI. - bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n") - bw.WriteString("Upgrade: websocket\r\n") - bw.WriteString("Connection: Upgrade\r\n") - nonce := generateNonce() - if config.handshakeData != nil { - nonce = []byte(config.handshakeData["key"]) - } - bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n") - bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") - - if config.Version != ProtocolVersionHybi13 { - return ErrBadProtocolVersion - } - - bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n") - if len(config.Protocol) > 0 { - bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n") - } - // TODO(ukai): send Sec-WebSocket-Extensions. - err = config.Header.WriteSubset(bw, handshakeHeader) - if err != nil { - return err - } - - bw.WriteString("\r\n") - if err = bw.Flush(); err != nil { - return err - } - - resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) - if err != nil { - return err - } - if resp.StatusCode != 101 { - return ErrBadStatus - } - if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" || - strings.ToLower(resp.Header.Get("Connection")) != "upgrade" { - return ErrBadUpgrade - } - expectedAccept, err := getNonceAccept(nonce) - if err != nil { - return err - } - if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) { - return ErrChallengeResponse - } - if resp.Header.Get("Sec-WebSocket-Extensions") != "" { - return ErrUnsupportedExtensions - } - offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol") - if offeredProtocol != "" { - protocolMatched := false - for i := 0; i < len(config.Protocol); i++ { - if config.Protocol[i] == offeredProtocol { - protocolMatched = true - break - } - } - if !protocolMatched { - return ErrBadWebSocketProtocol - } - config.Protocol = []string{offeredProtocol} - } - - return nil -} - -// newHybiClientConn creates a client WebSocket connection after handshake. -func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn { - return newHybiConn(config, buf, rwc, nil) -} - -// A HybiServerHandshaker performs a server handshake using hybi draft protocol. -type hybiServerHandshaker struct { - *Config - accept []byte -} - -func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) { - c.Version = ProtocolVersionHybi13 - if req.Method != "GET" { - return http.StatusMethodNotAllowed, ErrBadRequestMethod - } - // HTTP version can be safely ignored. - - if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" || - !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") { - return http.StatusBadRequest, ErrNotWebSocket - } - - key := req.Header.Get("Sec-Websocket-Key") - if key == "" { - return http.StatusBadRequest, ErrChallengeResponse - } - version := req.Header.Get("Sec-Websocket-Version") - switch version { - case "13": - c.Version = ProtocolVersionHybi13 - default: - return http.StatusBadRequest, ErrBadWebSocketVersion - } - var scheme string - if req.TLS != nil { - scheme = "wss" - } else { - scheme = "ws" - } - c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI()) - if err != nil { - return http.StatusBadRequest, err - } - protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol")) - if protocol != "" { - protocols := strings.Split(protocol, ",") - for i := 0; i < len(protocols); i++ { - c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i])) - } - } - c.accept, err = getNonceAccept([]byte(key)) - if err != nil { - return http.StatusInternalServerError, err - } - return http.StatusSwitchingProtocols, nil -} - -// Origin parses the Origin header in req. -// If the Origin header is not set, it returns nil and nil. -func Origin(config *Config, req *http.Request) (*url.URL, error) { - var origin string - switch config.Version { - case ProtocolVersionHybi13: - origin = req.Header.Get("Origin") - } - if origin == "" { - return nil, nil - } - return url.ParseRequestURI(origin) -} - -func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) { - if len(c.Protocol) > 0 { - if len(c.Protocol) != 1 { - // You need choose a Protocol in Handshake func in Server. - return ErrBadWebSocketProtocol - } - } - buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n") - buf.WriteString("Upgrade: websocket\r\n") - buf.WriteString("Connection: Upgrade\r\n") - buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n") - if len(c.Protocol) > 0 { - buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n") - } - // TODO(ukai): send Sec-WebSocket-Extensions. - if c.Header != nil { - err := c.Header.WriteSubset(buf, handshakeHeader) - if err != nil { - return err - } - } - buf.WriteString("\r\n") - return buf.Flush() -} - -func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn { - return newHybiServerConn(c.Config, buf, rwc, request) -} - -// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol. -func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn { - return newHybiConn(config, buf, rwc, request) -} diff --git a/vendor/golang.org/x/net/websocket/server.go b/vendor/golang.org/x/net/websocket/server.go deleted file mode 100644 index 0895dea19..000000000 --- a/vendor/golang.org/x/net/websocket/server.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package websocket - -import ( - "bufio" - "fmt" - "io" - "net/http" -) - -func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) { - var hs serverHandshaker = &hybiServerHandshaker{Config: config} - code, err := hs.ReadHandshake(buf.Reader, req) - if err == ErrBadWebSocketVersion { - fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) - fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion) - buf.WriteString("\r\n") - buf.WriteString(err.Error()) - buf.Flush() - return - } - if err != nil { - fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) - buf.WriteString("\r\n") - buf.WriteString(err.Error()) - buf.Flush() - return - } - if handshake != nil { - err = handshake(config, req) - if err != nil { - code = http.StatusForbidden - fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) - buf.WriteString("\r\n") - buf.Flush() - return - } - } - err = hs.AcceptHandshake(buf.Writer) - if err != nil { - code = http.StatusBadRequest - fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) - buf.WriteString("\r\n") - buf.Flush() - return - } - conn = hs.NewServerConn(buf, rwc, req) - return -} - -// Server represents a server of a WebSocket. -type Server struct { - // Config is a WebSocket configuration for new WebSocket connection. - Config - - // Handshake is an optional function in WebSocket handshake. - // For example, you can check, or don't check Origin header. - // Another example, you can select config.Protocol. - Handshake func(*Config, *http.Request) error - - // Handler handles a WebSocket connection. - Handler -} - -// ServeHTTP implements the http.Handler interface for a WebSocket -func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { - s.serveWebSocket(w, req) -} - -func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) { - rwc, buf, err := w.(http.Hijacker).Hijack() - if err != nil { - panic("Hijack failed: " + err.Error()) - } - // The server should abort the WebSocket connection if it finds - // the client did not send a handshake that matches with protocol - // specification. - defer rwc.Close() - conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake) - if err != nil { - return - } - if conn == nil { - panic("unexpected nil conn") - } - s.Handler(conn) -} - -// Handler is a simple interface to a WebSocket browser client. -// It checks if Origin header is valid URL by default. -// You might want to verify websocket.Conn.Config().Origin in the func. -// If you use Server instead of Handler, you could call websocket.Origin and -// check the origin in your Handshake func. So, if you want to accept -// non-browser clients, which do not send an Origin header, set a -// Server.Handshake that does not check the origin. -type Handler func(*Conn) - -func checkOrigin(config *Config, req *http.Request) (err error) { - config.Origin, err = Origin(config, req) - if err == nil && config.Origin == nil { - return fmt.Errorf("null origin") - } - return err -} - -// ServeHTTP implements the http.Handler interface for a WebSocket -func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - s := Server{Handler: h, Handshake: checkOrigin} - s.serveWebSocket(w, req) -} diff --git a/vendor/golang.org/x/net/websocket/websocket.go b/vendor/golang.org/x/net/websocket/websocket.go deleted file mode 100644 index 1f4f7be40..000000000 --- a/vendor/golang.org/x/net/websocket/websocket.go +++ /dev/null @@ -1,451 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package websocket implements a client and server for the WebSocket protocol -// as specified in RFC 6455. -// -// This package currently lacks some features found in an alternative -// and more actively maintained WebSocket package: -// -// https://godoc.org/github.com/gorilla/websocket -// -package websocket // import "golang.org/x/net/websocket" - -import ( - "bufio" - "crypto/tls" - "encoding/json" - "errors" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "sync" - "time" -) - -const ( - ProtocolVersionHybi13 = 13 - ProtocolVersionHybi = ProtocolVersionHybi13 - SupportedProtocolVersion = "13" - - ContinuationFrame = 0 - TextFrame = 1 - BinaryFrame = 2 - CloseFrame = 8 - PingFrame = 9 - PongFrame = 10 - UnknownFrame = 255 - - DefaultMaxPayloadBytes = 32 << 20 // 32MB -) - -// ProtocolError represents WebSocket protocol errors. -type ProtocolError struct { - ErrorString string -} - -func (err *ProtocolError) Error() string { return err.ErrorString } - -var ( - ErrBadProtocolVersion = &ProtocolError{"bad protocol version"} - ErrBadScheme = &ProtocolError{"bad scheme"} - ErrBadStatus = &ProtocolError{"bad status"} - ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"} - ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"} - ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"} - ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"} - ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"} - ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"} - ErrBadFrame = &ProtocolError{"bad frame"} - ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"} - ErrNotWebSocket = &ProtocolError{"not websocket protocol"} - ErrBadRequestMethod = &ProtocolError{"bad method"} - ErrNotSupported = &ProtocolError{"not supported"} -) - -// ErrFrameTooLarge is returned by Codec's Receive method if payload size -// exceeds limit set by Conn.MaxPayloadBytes -var ErrFrameTooLarge = errors.New("websocket: frame payload size exceeds limit") - -// Addr is an implementation of net.Addr for WebSocket. -type Addr struct { - *url.URL -} - -// Network returns the network type for a WebSocket, "websocket". -func (addr *Addr) Network() string { return "websocket" } - -// Config is a WebSocket configuration -type Config struct { - // A WebSocket server address. - Location *url.URL - - // A Websocket client origin. - Origin *url.URL - - // WebSocket subprotocols. - Protocol []string - - // WebSocket protocol version. - Version int - - // TLS config for secure WebSocket (wss). - TlsConfig *tls.Config - - // Additional header fields to be sent in WebSocket opening handshake. - Header http.Header - - // Dialer used when opening websocket connections. - Dialer *net.Dialer - - handshakeData map[string]string -} - -// serverHandshaker is an interface to handle WebSocket server side handshake. -type serverHandshaker interface { - // ReadHandshake reads handshake request message from client. - // Returns http response code and error if any. - ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) - - // AcceptHandshake accepts the client handshake request and sends - // handshake response back to client. - AcceptHandshake(buf *bufio.Writer) (err error) - - // NewServerConn creates a new WebSocket connection. - NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) -} - -// frameReader is an interface to read a WebSocket frame. -type frameReader interface { - // Reader is to read payload of the frame. - io.Reader - - // PayloadType returns payload type. - PayloadType() byte - - // HeaderReader returns a reader to read header of the frame. - HeaderReader() io.Reader - - // TrailerReader returns a reader to read trailer of the frame. - // If it returns nil, there is no trailer in the frame. - TrailerReader() io.Reader - - // Len returns total length of the frame, including header and trailer. - Len() int -} - -// frameReaderFactory is an interface to creates new frame reader. -type frameReaderFactory interface { - NewFrameReader() (r frameReader, err error) -} - -// frameWriter is an interface to write a WebSocket frame. -type frameWriter interface { - // Writer is to write payload of the frame. - io.WriteCloser -} - -// frameWriterFactory is an interface to create new frame writer. -type frameWriterFactory interface { - NewFrameWriter(payloadType byte) (w frameWriter, err error) -} - -type frameHandler interface { - HandleFrame(frame frameReader) (r frameReader, err error) - WriteClose(status int) (err error) -} - -// Conn represents a WebSocket connection. -// -// Multiple goroutines may invoke methods on a Conn simultaneously. -type Conn struct { - config *Config - request *http.Request - - buf *bufio.ReadWriter - rwc io.ReadWriteCloser - - rio sync.Mutex - frameReaderFactory - frameReader - - wio sync.Mutex - frameWriterFactory - - frameHandler - PayloadType byte - defaultCloseStatus int - - // MaxPayloadBytes limits the size of frame payload received over Conn - // by Codec's Receive method. If zero, DefaultMaxPayloadBytes is used. - MaxPayloadBytes int -} - -// Read implements the io.Reader interface: -// it reads data of a frame from the WebSocket connection. -// if msg is not large enough for the frame data, it fills the msg and next Read -// will read the rest of the frame data. -// it reads Text frame or Binary frame. -func (ws *Conn) Read(msg []byte) (n int, err error) { - ws.rio.Lock() - defer ws.rio.Unlock() -again: - if ws.frameReader == nil { - frame, err := ws.frameReaderFactory.NewFrameReader() - if err != nil { - return 0, err - } - ws.frameReader, err = ws.frameHandler.HandleFrame(frame) - if err != nil { - return 0, err - } - if ws.frameReader == nil { - goto again - } - } - n, err = ws.frameReader.Read(msg) - if err == io.EOF { - if trailer := ws.frameReader.TrailerReader(); trailer != nil { - io.Copy(ioutil.Discard, trailer) - } - ws.frameReader = nil - goto again - } - return n, err -} - -// Write implements the io.Writer interface: -// it writes data as a frame to the WebSocket connection. -func (ws *Conn) Write(msg []byte) (n int, err error) { - ws.wio.Lock() - defer ws.wio.Unlock() - w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType) - if err != nil { - return 0, err - } - n, err = w.Write(msg) - w.Close() - return n, err -} - -// Close implements the io.Closer interface. -func (ws *Conn) Close() error { - err := ws.frameHandler.WriteClose(ws.defaultCloseStatus) - err1 := ws.rwc.Close() - if err != nil { - return err - } - return err1 -} - -// IsClientConn reports whether ws is a client-side connection. -func (ws *Conn) IsClientConn() bool { return ws.request == nil } - -// IsServerConn reports whether ws is a server-side connection. -func (ws *Conn) IsServerConn() bool { return ws.request != nil } - -// LocalAddr returns the WebSocket Origin for the connection for client, or -// the WebSocket location for server. -func (ws *Conn) LocalAddr() net.Addr { - if ws.IsClientConn() { - return &Addr{ws.config.Origin} - } - return &Addr{ws.config.Location} -} - -// RemoteAddr returns the WebSocket location for the connection for client, or -// the Websocket Origin for server. -func (ws *Conn) RemoteAddr() net.Addr { - if ws.IsClientConn() { - return &Addr{ws.config.Location} - } - return &Addr{ws.config.Origin} -} - -var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn") - -// SetDeadline sets the connection's network read & write deadlines. -func (ws *Conn) SetDeadline(t time.Time) error { - if conn, ok := ws.rwc.(net.Conn); ok { - return conn.SetDeadline(t) - } - return errSetDeadline -} - -// SetReadDeadline sets the connection's network read deadline. -func (ws *Conn) SetReadDeadline(t time.Time) error { - if conn, ok := ws.rwc.(net.Conn); ok { - return conn.SetReadDeadline(t) - } - return errSetDeadline -} - -// SetWriteDeadline sets the connection's network write deadline. -func (ws *Conn) SetWriteDeadline(t time.Time) error { - if conn, ok := ws.rwc.(net.Conn); ok { - return conn.SetWriteDeadline(t) - } - return errSetDeadline -} - -// Config returns the WebSocket config. -func (ws *Conn) Config() *Config { return ws.config } - -// Request returns the http request upgraded to the WebSocket. -// It is nil for client side. -func (ws *Conn) Request() *http.Request { return ws.request } - -// Codec represents a symmetric pair of functions that implement a codec. -type Codec struct { - Marshal func(v interface{}) (data []byte, payloadType byte, err error) - Unmarshal func(data []byte, payloadType byte, v interface{}) (err error) -} - -// Send sends v marshaled by cd.Marshal as single frame to ws. -func (cd Codec) Send(ws *Conn, v interface{}) (err error) { - data, payloadType, err := cd.Marshal(v) - if err != nil { - return err - } - ws.wio.Lock() - defer ws.wio.Unlock() - w, err := ws.frameWriterFactory.NewFrameWriter(payloadType) - if err != nil { - return err - } - _, err = w.Write(data) - w.Close() - return err -} - -// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores -// in v. The whole frame payload is read to an in-memory buffer; max size of -// payload is defined by ws.MaxPayloadBytes. If frame payload size exceeds -// limit, ErrFrameTooLarge is returned; in this case frame is not read off wire -// completely. The next call to Receive would read and discard leftover data of -// previous oversized frame before processing next frame. -func (cd Codec) Receive(ws *Conn, v interface{}) (err error) { - ws.rio.Lock() - defer ws.rio.Unlock() - if ws.frameReader != nil { - _, err = io.Copy(ioutil.Discard, ws.frameReader) - if err != nil { - return err - } - ws.frameReader = nil - } -again: - frame, err := ws.frameReaderFactory.NewFrameReader() - if err != nil { - return err - } - frame, err = ws.frameHandler.HandleFrame(frame) - if err != nil { - return err - } - if frame == nil { - goto again - } - maxPayloadBytes := ws.MaxPayloadBytes - if maxPayloadBytes == 0 { - maxPayloadBytes = DefaultMaxPayloadBytes - } - if hf, ok := frame.(*hybiFrameReader); ok && hf.header.Length > int64(maxPayloadBytes) { - // payload size exceeds limit, no need to call Unmarshal - // - // set frameReader to current oversized frame so that - // the next call to this function can drain leftover - // data before processing the next frame - ws.frameReader = frame - return ErrFrameTooLarge - } - payloadType := frame.PayloadType() - data, err := ioutil.ReadAll(frame) - if err != nil { - return err - } - return cd.Unmarshal(data, payloadType, v) -} - -func marshal(v interface{}) (msg []byte, payloadType byte, err error) { - switch data := v.(type) { - case string: - return []byte(data), TextFrame, nil - case []byte: - return data, BinaryFrame, nil - } - return nil, UnknownFrame, ErrNotSupported -} - -func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) { - switch data := v.(type) { - case *string: - *data = string(msg) - return nil - case *[]byte: - *data = msg - return nil - } - return ErrNotSupported -} - -/* -Message is a codec to send/receive text/binary data in a frame on WebSocket connection. -To send/receive text frame, use string type. -To send/receive binary frame, use []byte type. - -Trivial usage: - - import "websocket" - - // receive text frame - var message string - websocket.Message.Receive(ws, &message) - - // send text frame - message = "hello" - websocket.Message.Send(ws, message) - - // receive binary frame - var data []byte - websocket.Message.Receive(ws, &data) - - // send binary frame - data = []byte{0, 1, 2} - websocket.Message.Send(ws, data) - -*/ -var Message = Codec{marshal, unmarshal} - -func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) { - msg, err = json.Marshal(v) - return msg, TextFrame, err -} - -func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) { - return json.Unmarshal(msg, v) -} - -/* -JSON is a codec to send/receive JSON data in a frame from a WebSocket connection. - -Trivial usage: - - import "websocket" - - type T struct { - Msg string - Count int - } - - // receive JSON type T - var data T - websocket.JSON.Receive(ws, &data) - - // send JSON type T - websocket.JSON.Send(ws, data) -*/ -var JSON = Codec{jsonMarshal, jsonUnmarshal} diff --git a/vendor/golang.org/x/sync/syncmap/go19.go b/vendor/golang.org/x/sync/syncmap/go19.go new file mode 100644 index 000000000..41a59091e --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/go19.go @@ -0,0 +1,17 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package syncmap + +import "sync" // home to the standard library's sync.map implementation as of Go 1.9 + +// Map is a concurrent map with amortized-constant-time loads, stores, and deletes. +// It is safe for multiple goroutines to call a Map's methods concurrently. +// +// The zero Map is valid and empty. +// +// A Map must not be copied after first use. +type Map = sync.Map diff --git a/vendor/golang.org/x/sync/syncmap/map.go b/vendor/golang.org/x/sync/syncmap/map.go index 80e15847e..4b638cb7a 100644 --- a/vendor/golang.org/x/sync/syncmap/map.go +++ b/vendor/golang.org/x/sync/syncmap/map.go @@ -1,372 +1,8 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package syncmap provides a concurrent map implementation. -// It is a prototype for a proposed addition to the sync package -// in the standard library. -// (https://golang.org/issue/18177) +// This was the prototype for sync.Map which was added to the standard library's +// sync package in Go 1.9. https://golang.org/pkg/sync/#Map. package syncmap - -import ( - "sync" - "sync/atomic" - "unsafe" -) - -// Map is a concurrent map with amortized-constant-time loads, stores, and deletes. -// It is safe for multiple goroutines to call a Map's methods concurrently. -// -// The zero Map is valid and empty. -// -// A Map must not be copied after first use. -type Map struct { - mu sync.Mutex - - // read contains the portion of the map's contents that are safe for - // concurrent access (with or without mu held). - // - // The read field itself is always safe to load, but must only be stored with - // mu held. - // - // Entries stored in read may be updated concurrently without mu, but updating - // a previously-expunged entry requires that the entry be copied to the dirty - // map and unexpunged with mu held. - read atomic.Value // readOnly - - // dirty contains the portion of the map's contents that require mu to be - // held. To ensure that the dirty map can be promoted to the read map quickly, - // it also includes all of the non-expunged entries in the read map. - // - // Expunged entries are not stored in the dirty map. An expunged entry in the - // clean map must be unexpunged and added to the dirty map before a new value - // can be stored to it. - // - // If the dirty map is nil, the next write to the map will initialize it by - // making a shallow copy of the clean map, omitting stale entries. - dirty map[interface{}]*entry - - // misses counts the number of loads since the read map was last updated that - // needed to lock mu to determine whether the key was present. - // - // Once enough misses have occurred to cover the cost of copying the dirty - // map, the dirty map will be promoted to the read map (in the unamended - // state) and the next store to the map will make a new dirty copy. - misses int -} - -// readOnly is an immutable struct stored atomically in the Map.read field. -type readOnly struct { - m map[interface{}]*entry - amended bool // true if the dirty map contains some key not in m. -} - -// expunged is an arbitrary pointer that marks entries which have been deleted -// from the dirty map. -var expunged = unsafe.Pointer(new(interface{})) - -// An entry is a slot in the map corresponding to a particular key. -type entry struct { - // p points to the interface{} value stored for the entry. - // - // If p == nil, the entry has been deleted and m.dirty == nil. - // - // If p == expunged, the entry has been deleted, m.dirty != nil, and the entry - // is missing from m.dirty. - // - // Otherwise, the entry is valid and recorded in m.read.m[key] and, if m.dirty - // != nil, in m.dirty[key]. - // - // An entry can be deleted by atomic replacement with nil: when m.dirty is - // next created, it will atomically replace nil with expunged and leave - // m.dirty[key] unset. - // - // An entry's associated value can be updated by atomic replacement, provided - // p != expunged. If p == expunged, an entry's associated value can be updated - // only after first setting m.dirty[key] = e so that lookups using the dirty - // map find the entry. - p unsafe.Pointer // *interface{} -} - -func newEntry(i interface{}) *entry { - return &entry{p: unsafe.Pointer(&i)} -} - -// Load returns the value stored in the map for a key, or nil if no -// value is present. -// The ok result indicates whether value was found in the map. -func (m *Map) Load(key interface{}) (value interface{}, ok bool) { - read, _ := m.read.Load().(readOnly) - e, ok := read.m[key] - if !ok && read.amended { - m.mu.Lock() - // Avoid reporting a spurious miss if m.dirty got promoted while we were - // blocked on m.mu. (If further loads of the same key will not miss, it's - // not worth copying the dirty map for this key.) - read, _ = m.read.Load().(readOnly) - e, ok = read.m[key] - if !ok && read.amended { - e, ok = m.dirty[key] - // Regardless of whether the entry was present, record a miss: this key - // will take the slow path until the dirty map is promoted to the read - // map. - m.missLocked() - } - m.mu.Unlock() - } - if !ok { - return nil, false - } - return e.load() -} - -func (e *entry) load() (value interface{}, ok bool) { - p := atomic.LoadPointer(&e.p) - if p == nil || p == expunged { - return nil, false - } - return *(*interface{})(p), true -} - -// Store sets the value for a key. -func (m *Map) Store(key, value interface{}) { - read, _ := m.read.Load().(readOnly) - if e, ok := read.m[key]; ok && e.tryStore(&value) { - return - } - - m.mu.Lock() - read, _ = m.read.Load().(readOnly) - if e, ok := read.m[key]; ok { - if e.unexpungeLocked() { - // The entry was previously expunged, which implies that there is a - // non-nil dirty map and this entry is not in it. - m.dirty[key] = e - } - e.storeLocked(&value) - } else if e, ok := m.dirty[key]; ok { - e.storeLocked(&value) - } else { - if !read.amended { - // We're adding the first new key to the dirty map. - // Make sure it is allocated and mark the read-only map as incomplete. - m.dirtyLocked() - m.read.Store(readOnly{m: read.m, amended: true}) - } - m.dirty[key] = newEntry(value) - } - m.mu.Unlock() -} - -// tryStore stores a value if the entry has not been expunged. -// -// If the entry is expunged, tryStore returns false and leaves the entry -// unchanged. -func (e *entry) tryStore(i *interface{}) bool { - p := atomic.LoadPointer(&e.p) - if p == expunged { - return false - } - for { - if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) { - return true - } - p = atomic.LoadPointer(&e.p) - if p == expunged { - return false - } - } -} - -// unexpungeLocked ensures that the entry is not marked as expunged. -// -// If the entry was previously expunged, it must be added to the dirty map -// before m.mu is unlocked. -func (e *entry) unexpungeLocked() (wasExpunged bool) { - return atomic.CompareAndSwapPointer(&e.p, expunged, nil) -} - -// storeLocked unconditionally stores a value to the entry. -// -// The entry must be known not to be expunged. -func (e *entry) storeLocked(i *interface{}) { - atomic.StorePointer(&e.p, unsafe.Pointer(i)) -} - -// LoadOrStore returns the existing value for the key if present. -// Otherwise, it stores and returns the given value. -// The loaded result is true if the value was loaded, false if stored. -func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { - // Avoid locking if it's a clean hit. - read, _ := m.read.Load().(readOnly) - if e, ok := read.m[key]; ok { - actual, loaded, ok := e.tryLoadOrStore(value) - if ok { - return actual, loaded - } - } - - m.mu.Lock() - read, _ = m.read.Load().(readOnly) - if e, ok := read.m[key]; ok { - if e.unexpungeLocked() { - m.dirty[key] = e - } - actual, loaded, _ = e.tryLoadOrStore(value) - } else if e, ok := m.dirty[key]; ok { - actual, loaded, _ = e.tryLoadOrStore(value) - m.missLocked() - } else { - if !read.amended { - // We're adding the first new key to the dirty map. - // Make sure it is allocated and mark the read-only map as incomplete. - m.dirtyLocked() - m.read.Store(readOnly{m: read.m, amended: true}) - } - m.dirty[key] = newEntry(value) - actual, loaded = value, false - } - m.mu.Unlock() - - return actual, loaded -} - -// tryLoadOrStore atomically loads or stores a value if the entry is not -// expunged. -// -// If the entry is expunged, tryLoadOrStore leaves the entry unchanged and -// returns with ok==false. -func (e *entry) tryLoadOrStore(i interface{}) (actual interface{}, loaded, ok bool) { - p := atomic.LoadPointer(&e.p) - if p == expunged { - return nil, false, false - } - if p != nil { - return *(*interface{})(p), true, true - } - - // Copy the interface after the first load to make this method more amenable - // to escape analysis: if we hit the "load" path or the entry is expunged, we - // shouldn't bother heap-allocating. - ic := i - for { - if atomic.CompareAndSwapPointer(&e.p, nil, unsafe.Pointer(&ic)) { - return i, false, true - } - p = atomic.LoadPointer(&e.p) - if p == expunged { - return nil, false, false - } - if p != nil { - return *(*interface{})(p), true, true - } - } -} - -// Delete deletes the value for a key. -func (m *Map) Delete(key interface{}) { - read, _ := m.read.Load().(readOnly) - e, ok := read.m[key] - if !ok && read.amended { - m.mu.Lock() - read, _ = m.read.Load().(readOnly) - e, ok = read.m[key] - if !ok && read.amended { - delete(m.dirty, key) - } - m.mu.Unlock() - } - if ok { - e.delete() - } -} - -func (e *entry) delete() (hadValue bool) { - for { - p := atomic.LoadPointer(&e.p) - if p == nil || p == expunged { - return false - } - if atomic.CompareAndSwapPointer(&e.p, p, nil) { - return true - } - } -} - -// Range calls f sequentially for each key and value present in the map. -// If f returns false, range stops the iteration. -// -// Range does not necessarily correspond to any consistent snapshot of the Map's -// contents: no key will be visited more than once, but if the value for any key -// is stored or deleted concurrently, Range may reflect any mapping for that key -// from any point during the Range call. -// -// Range may be O(N) with the number of elements in the map even if f returns -// false after a constant number of calls. -func (m *Map) Range(f func(key, value interface{}) bool) { - // We need to be able to iterate over all of the keys that were already - // present at the start of the call to Range. - // If read.amended is false, then read.m satisfies that property without - // requiring us to hold m.mu for a long time. - read, _ := m.read.Load().(readOnly) - if read.amended { - // m.dirty contains keys not in read.m. Fortunately, Range is already O(N) - // (assuming the caller does not break out early), so a call to Range - // amortizes an entire copy of the map: we can promote the dirty copy - // immediately! - m.mu.Lock() - read, _ = m.read.Load().(readOnly) - if read.amended { - read = readOnly{m: m.dirty} - m.read.Store(read) - m.dirty = nil - m.misses = 0 - } - m.mu.Unlock() - } - - for k, e := range read.m { - v, ok := e.load() - if !ok { - continue - } - if !f(k, v) { - break - } - } -} - -func (m *Map) missLocked() { - m.misses++ - if m.misses < len(m.dirty) { - return - } - m.read.Store(readOnly{m: m.dirty}) - m.dirty = nil - m.misses = 0 -} - -func (m *Map) dirtyLocked() { - if m.dirty != nil { - return - } - - read, _ := m.read.Load().(readOnly) - m.dirty = make(map[interface{}]*entry, len(read.m)) - for k, e := range read.m { - if !e.tryExpungeLocked() { - m.dirty[k] = e - } - } -} - -func (e *entry) tryExpungeLocked() (isExpunged bool) { - p := atomic.LoadPointer(&e.p) - for p == nil { - if atomic.CompareAndSwapPointer(&e.p, nil, expunged) { - return true - } - p = atomic.LoadPointer(&e.p) - } - return p == expunged -} diff --git a/vendor/golang.org/x/sync/syncmap/pre_go19.go b/vendor/golang.org/x/sync/syncmap/pre_go19.go new file mode 100644 index 000000000..01a7be7f9 --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/pre_go19.go @@ -0,0 +1,370 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.9 + +package syncmap + +import ( + "sync" + "sync/atomic" + "unsafe" +) + +// Map is a concurrent map with amortized-constant-time loads, stores, and deletes. +// It is safe for multiple goroutines to call a Map's methods concurrently. +// +// The zero Map is valid and empty. +// +// A Map must not be copied after first use. +type Map struct { + mu sync.Mutex + + // read contains the portion of the map's contents that are safe for + // concurrent access (with or without mu held). + // + // The read field itself is always safe to load, but must only be stored with + // mu held. + // + // Entries stored in read may be updated concurrently without mu, but updating + // a previously-expunged entry requires that the entry be copied to the dirty + // map and unexpunged with mu held. + read atomic.Value // readOnly + + // dirty contains the portion of the map's contents that require mu to be + // held. To ensure that the dirty map can be promoted to the read map quickly, + // it also includes all of the non-expunged entries in the read map. + // + // Expunged entries are not stored in the dirty map. An expunged entry in the + // clean map must be unexpunged and added to the dirty map before a new value + // can be stored to it. + // + // If the dirty map is nil, the next write to the map will initialize it by + // making a shallow copy of the clean map, omitting stale entries. + dirty map[interface{}]*entry + + // misses counts the number of loads since the read map was last updated that + // needed to lock mu to determine whether the key was present. + // + // Once enough misses have occurred to cover the cost of copying the dirty + // map, the dirty map will be promoted to the read map (in the unamended + // state) and the next store to the map will make a new dirty copy. + misses int +} + +// readOnly is an immutable struct stored atomically in the Map.read field. +type readOnly struct { + m map[interface{}]*entry + amended bool // true if the dirty map contains some key not in m. +} + +// expunged is an arbitrary pointer that marks entries which have been deleted +// from the dirty map. +var expunged = unsafe.Pointer(new(interface{})) + +// An entry is a slot in the map corresponding to a particular key. +type entry struct { + // p points to the interface{} value stored for the entry. + // + // If p == nil, the entry has been deleted and m.dirty == nil. + // + // If p == expunged, the entry has been deleted, m.dirty != nil, and the entry + // is missing from m.dirty. + // + // Otherwise, the entry is valid and recorded in m.read.m[key] and, if m.dirty + // != nil, in m.dirty[key]. + // + // An entry can be deleted by atomic replacement with nil: when m.dirty is + // next created, it will atomically replace nil with expunged and leave + // m.dirty[key] unset. + // + // An entry's associated value can be updated by atomic replacement, provided + // p != expunged. If p == expunged, an entry's associated value can be updated + // only after first setting m.dirty[key] = e so that lookups using the dirty + // map find the entry. + p unsafe.Pointer // *interface{} +} + +func newEntry(i interface{}) *entry { + return &entry{p: unsafe.Pointer(&i)} +} + +// Load returns the value stored in the map for a key, or nil if no +// value is present. +// The ok result indicates whether value was found in the map. +func (m *Map) Load(key interface{}) (value interface{}, ok bool) { + read, _ := m.read.Load().(readOnly) + e, ok := read.m[key] + if !ok && read.amended { + m.mu.Lock() + // Avoid reporting a spurious miss if m.dirty got promoted while we were + // blocked on m.mu. (If further loads of the same key will not miss, it's + // not worth copying the dirty map for this key.) + read, _ = m.read.Load().(readOnly) + e, ok = read.m[key] + if !ok && read.amended { + e, ok = m.dirty[key] + // Regardless of whether the entry was present, record a miss: this key + // will take the slow path until the dirty map is promoted to the read + // map. + m.missLocked() + } + m.mu.Unlock() + } + if !ok { + return nil, false + } + return e.load() +} + +func (e *entry) load() (value interface{}, ok bool) { + p := atomic.LoadPointer(&e.p) + if p == nil || p == expunged { + return nil, false + } + return *(*interface{})(p), true +} + +// Store sets the value for a key. +func (m *Map) Store(key, value interface{}) { + read, _ := m.read.Load().(readOnly) + if e, ok := read.m[key]; ok && e.tryStore(&value) { + return + } + + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + if e.unexpungeLocked() { + // The entry was previously expunged, which implies that there is a + // non-nil dirty map and this entry is not in it. + m.dirty[key] = e + } + e.storeLocked(&value) + } else if e, ok := m.dirty[key]; ok { + e.storeLocked(&value) + } else { + if !read.amended { + // We're adding the first new key to the dirty map. + // Make sure it is allocated and mark the read-only map as incomplete. + m.dirtyLocked() + m.read.Store(readOnly{m: read.m, amended: true}) + } + m.dirty[key] = newEntry(value) + } + m.mu.Unlock() +} + +// tryStore stores a value if the entry has not been expunged. +// +// If the entry is expunged, tryStore returns false and leaves the entry +// unchanged. +func (e *entry) tryStore(i *interface{}) bool { + p := atomic.LoadPointer(&e.p) + if p == expunged { + return false + } + for { + if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) { + return true + } + p = atomic.LoadPointer(&e.p) + if p == expunged { + return false + } + } +} + +// unexpungeLocked ensures that the entry is not marked as expunged. +// +// If the entry was previously expunged, it must be added to the dirty map +// before m.mu is unlocked. +func (e *entry) unexpungeLocked() (wasExpunged bool) { + return atomic.CompareAndSwapPointer(&e.p, expunged, nil) +} + +// storeLocked unconditionally stores a value to the entry. +// +// The entry must be known not to be expunged. +func (e *entry) storeLocked(i *interface{}) { + atomic.StorePointer(&e.p, unsafe.Pointer(i)) +} + +// LoadOrStore returns the existing value for the key if present. +// Otherwise, it stores and returns the given value. +// The loaded result is true if the value was loaded, false if stored. +func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + // Avoid locking if it's a clean hit. + read, _ := m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + actual, loaded, ok := e.tryLoadOrStore(value) + if ok { + return actual, loaded + } + } + + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + if e.unexpungeLocked() { + m.dirty[key] = e + } + actual, loaded, _ = e.tryLoadOrStore(value) + } else if e, ok := m.dirty[key]; ok { + actual, loaded, _ = e.tryLoadOrStore(value) + m.missLocked() + } else { + if !read.amended { + // We're adding the first new key to the dirty map. + // Make sure it is allocated and mark the read-only map as incomplete. + m.dirtyLocked() + m.read.Store(readOnly{m: read.m, amended: true}) + } + m.dirty[key] = newEntry(value) + actual, loaded = value, false + } + m.mu.Unlock() + + return actual, loaded +} + +// tryLoadOrStore atomically loads or stores a value if the entry is not +// expunged. +// +// If the entry is expunged, tryLoadOrStore leaves the entry unchanged and +// returns with ok==false. +func (e *entry) tryLoadOrStore(i interface{}) (actual interface{}, loaded, ok bool) { + p := atomic.LoadPointer(&e.p) + if p == expunged { + return nil, false, false + } + if p != nil { + return *(*interface{})(p), true, true + } + + // Copy the interface after the first load to make this method more amenable + // to escape analysis: if we hit the "load" path or the entry is expunged, we + // shouldn't bother heap-allocating. + ic := i + for { + if atomic.CompareAndSwapPointer(&e.p, nil, unsafe.Pointer(&ic)) { + return i, false, true + } + p = atomic.LoadPointer(&e.p) + if p == expunged { + return nil, false, false + } + if p != nil { + return *(*interface{})(p), true, true + } + } +} + +// Delete deletes the value for a key. +func (m *Map) Delete(key interface{}) { + read, _ := m.read.Load().(readOnly) + e, ok := read.m[key] + if !ok && read.amended { + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + e, ok = read.m[key] + if !ok && read.amended { + delete(m.dirty, key) + } + m.mu.Unlock() + } + if ok { + e.delete() + } +} + +func (e *entry) delete() (hadValue bool) { + for { + p := atomic.LoadPointer(&e.p) + if p == nil || p == expunged { + return false + } + if atomic.CompareAndSwapPointer(&e.p, p, nil) { + return true + } + } +} + +// Range calls f sequentially for each key and value present in the map. +// If f returns false, range stops the iteration. +// +// Range does not necessarily correspond to any consistent snapshot of the Map's +// contents: no key will be visited more than once, but if the value for any key +// is stored or deleted concurrently, Range may reflect any mapping for that key +// from any point during the Range call. +// +// Range may be O(N) with the number of elements in the map even if f returns +// false after a constant number of calls. +func (m *Map) Range(f func(key, value interface{}) bool) { + // We need to be able to iterate over all of the keys that were already + // present at the start of the call to Range. + // If read.amended is false, then read.m satisfies that property without + // requiring us to hold m.mu for a long time. + read, _ := m.read.Load().(readOnly) + if read.amended { + // m.dirty contains keys not in read.m. Fortunately, Range is already O(N) + // (assuming the caller does not break out early), so a call to Range + // amortizes an entire copy of the map: we can promote the dirty copy + // immediately! + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if read.amended { + read = readOnly{m: m.dirty} + m.read.Store(read) + m.dirty = nil + m.misses = 0 + } + m.mu.Unlock() + } + + for k, e := range read.m { + v, ok := e.load() + if !ok { + continue + } + if !f(k, v) { + break + } + } +} + +func (m *Map) missLocked() { + m.misses++ + if m.misses < len(m.dirty) { + return + } + m.read.Store(readOnly{m: m.dirty}) + m.dirty = nil + m.misses = 0 +} + +func (m *Map) dirtyLocked() { + if m.dirty != nil { + return + } + + read, _ := m.read.Load().(readOnly) + m.dirty = make(map[interface{}]*entry, len(read.m)) + for k, e := range read.m { + if !e.tryExpungeLocked() { + m.dirty[k] = e + } + } +} + +func (e *entry) tryExpungeLocked() (isExpunged bool) { + p := atomic.LoadPointer(&e.p) + for p == nil { + if atomic.CompareAndSwapPointer(&e.p, nil, expunged) { + return true + } + p = atomic.LoadPointer(&e.p) + } + return p == expunged +} diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go index da6b9e436..ed8da8dea 100644 --- a/vendor/golang.org/x/sys/cpu/byteorder.go +++ b/vendor/golang.org/x/sys/cpu/byteorder.go @@ -5,26 +5,56 @@ package cpu import ( - "encoding/binary" "runtime" ) +// byteOrder is a subset of encoding/binary.ByteOrder. +type byteOrder interface { + Uint32([]byte) uint32 + Uint64([]byte) uint64 +} + +type littleEndian struct{} +type bigEndian struct{} + +func (littleEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func (littleEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func (bigEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 +} + +func (bigEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + // hostByteOrder returns binary.LittleEndian on little-endian machines and // binary.BigEndian on big-endian machines. -func hostByteOrder() binary.ByteOrder { +func hostByteOrder() byteOrder { switch runtime.GOARCH { case "386", "amd64", "amd64p32", "arm", "arm64", "mipsle", "mips64le", "mips64p32le", "ppc64le", "riscv", "riscv64": - return binary.LittleEndian + return littleEndian{} case "armbe", "arm64be", "mips", "mips64", "mips64p32", "ppc", "ppc64", "s390", "s390x", "sparc", "sparc64": - return binary.BigEndian + return bigEndian{} } panic("unknown architecture") } diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go index 679e78c2c..b4e6ecb2d 100644 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -78,6 +78,42 @@ var ARM64 struct { _ CacheLinePad } +// ARM contains the supported CPU features of the current ARM (32-bit) platform. +// All feature flags are false if: +// 1. the current platform is not arm, or +// 2. the current operating system is not Linux. +var ARM struct { + _ CacheLinePad + HasSWP bool // SWP instruction support + HasHALF bool // Half-word load and store support + HasTHUMB bool // ARM Thumb instruction set + Has26BIT bool // Address space limited to 26-bits + HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support + HasFPA bool // Floating point arithmetic support + HasVFP bool // Vector floating point support + HasEDSP bool // DSP Extensions support + HasJAVA bool // Java instruction set + HasIWMMXT bool // Intel Wireless MMX technology support + HasCRUNCH bool // MaverickCrunch context switching and handling + HasTHUMBEE bool // Thumb EE instruction set + HasNEON bool // NEON instruction set + HasVFPv3 bool // Vector floating point version 3 support + HasVFPv3D16 bool // Vector floating point version 3 D8-D15 + HasTLS bool // Thread local storage support + HasVFPv4 bool // Vector floating point version 4 support + HasIDIVA bool // Integer divide instruction support in ARM mode + HasIDIVT bool // Integer divide instruction support in Thumb mode + HasVFPD32 bool // Vector floating point version 3 D15-D31 + HasLPAE bool // Large Physical Address Extensions + HasEVTSTRM bool // Event stream support + HasAES bool // AES hardware implementation + HasPMULL bool // Polynomial multiplication instruction set + HasSHA1 bool // SHA1 hardware implementation + HasSHA2 bool // SHA2 hardware implementation + HasCRC32 bool // CRC32 hardware implementation + _ CacheLinePad +} + // PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. // If the current platform is not ppc64/ppc64le then all feature flags are false. // diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go index 7f2348b7d..981af6818 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm.go +++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go @@ -6,4 +6,35 @@ package cpu const cacheLineSize = 32 -func doinit() {} +// HWCAP/HWCAP2 bits. +// These are specific to Linux. +const ( + hwcap_SWP = 1 << 0 + hwcap_HALF = 1 << 1 + hwcap_THUMB = 1 << 2 + hwcap_26BIT = 1 << 3 + hwcap_FAST_MULT = 1 << 4 + hwcap_FPA = 1 << 5 + hwcap_VFP = 1 << 6 + hwcap_EDSP = 1 << 7 + hwcap_JAVA = 1 << 8 + hwcap_IWMMXT = 1 << 9 + hwcap_CRUNCH = 1 << 10 + hwcap_THUMBEE = 1 << 11 + hwcap_NEON = 1 << 12 + hwcap_VFPv3 = 1 << 13 + hwcap_VFPv3D16 = 1 << 14 + hwcap_TLS = 1 << 15 + hwcap_VFPv4 = 1 << 16 + hwcap_IDIVA = 1 << 17 + hwcap_IDIVT = 1 << 18 + hwcap_VFPD32 = 1 << 19 + hwcap_LPAE = 1 << 20 + hwcap_EVTSTRM = 1 << 21 + + hwcap2_AES = 1 << 0 + hwcap2_PMULL = 1 << 1 + hwcap2_SHA1 = 1 << 2 + hwcap2_SHA2 = 1 << 3 + hwcap2_CRC32 = 1 << 4 +) diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go index 76b5f507f..10e712dc5 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//+build !amd64,!amd64p32,!386 +// +build !amd64,!amd64p32,!386 package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go new file mode 100644 index 000000000..2057006dc --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go @@ -0,0 +1,39 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +func doinit() { + ARM.HasSWP = isSet(hwCap, hwcap_SWP) + ARM.HasHALF = isSet(hwCap, hwcap_HALF) + ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB) + ARM.Has26BIT = isSet(hwCap, hwcap_26BIT) + ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT) + ARM.HasFPA = isSet(hwCap, hwcap_FPA) + ARM.HasVFP = isSet(hwCap, hwcap_VFP) + ARM.HasEDSP = isSet(hwCap, hwcap_EDSP) + ARM.HasJAVA = isSet(hwCap, hwcap_JAVA) + ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT) + ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH) + ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE) + ARM.HasNEON = isSet(hwCap, hwcap_NEON) + ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3) + ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16) + ARM.HasTLS = isSet(hwCap, hwcap_TLS) + ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4) + ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA) + ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT) + ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32) + ARM.HasLPAE = isSet(hwCap, hwcap_LPAE) + ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) + ARM.HasAES = isSet(hwCap2, hwcap2_AES) + ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL) + ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1) + ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2) + ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/unix/affinity_linux.go b/vendor/golang.org/x/sys/unix/affinity_linux.go index 14e4d5caa..6e5c81acd 100644 --- a/vendor/golang.org/x/sys/unix/affinity_linux.go +++ b/vendor/golang.org/x/sys/unix/affinity_linux.go @@ -7,6 +7,7 @@ package unix import ( + "math/bits" "unsafe" ) @@ -79,50 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool { func (s *CPUSet) Count() int { c := 0 for _, b := range s { - c += onesCount64(uint64(b)) + c += bits.OnesCount64(uint64(b)) } return c } - -// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64. -// Once this package can require Go 1.9, we can delete this -// and update the caller to use bits.OnesCount64. -func onesCount64(x uint64) int { - const m0 = 0x5555555555555555 // 01010101 ... - const m1 = 0x3333333333333333 // 00110011 ... - const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... - - // Unused in this function, but definitions preserved for - // documentation purposes: - // - // const m3 = 0x00ff00ff00ff00ff // etc. - // const m4 = 0x0000ffff0000ffff - // - // Implementation: Parallel summing of adjacent bits. - // See "Hacker's Delight", Chap. 5: Counting Bits. - // The following pattern shows the general approach: - // - // x = x>>1&(m0&m) + x&(m0&m) - // x = x>>2&(m1&m) + x&(m1&m) - // x = x>>4&(m2&m) + x&(m2&m) - // x = x>>8&(m3&m) + x&(m3&m) - // x = x>>16&(m4&m) + x&(m4&m) - // x = x>>32&(m5&m) + x&(m5&m) - // return int(x) - // - // Masking (& operations) can be left away when there's no - // danger that a field's sum will carry over into the next - // field: Since the result cannot be > 64, 8 bits is enough - // and we can ignore the masks for the shifts by 8 and up. - // Per "Hacker's Delight", the first line can be simplified - // more, but it saves at best one instruction, so we leave - // it alone for clarity. - const m = 1<<64 - 1 - x = x>>1&(m0&m) + x&(m0&m) - x = x>>2&(m1&m) + x&(m1&m) - x = (x>>4 + x) & (m2 & m) - x += x >> 8 - x += x >> 16 - x += x >> 32 - return int(x) & (1<<7 - 1) -} diff --git a/vendor/golang.org/x/sys/unix/ioctl.go b/vendor/golang.org/x/sys/unix/ioctl.go index f121a8d64..3559e5dcb 100644 --- a/vendor/golang.org/x/sys/unix/ioctl.go +++ b/vendor/golang.org/x/sys/unix/ioctl.go @@ -6,7 +6,19 @@ package unix -import "runtime" +import ( + "runtime" + "unsafe" +) + +// ioctl itself should not be exposed directly, but additional get/set +// functions for specific types are permissible. + +// IoctlSetInt performs an ioctl operation which sets an integer value +// on fd, using the specified request number. +func IoctlSetInt(fd int, req uint, value int) error { + return ioctl(fd, req, uintptr(value)) +} // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // @@ -14,7 +26,7 @@ import "runtime" func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // TODO: if we get the chance, remove the req parameter and // hardcode TIOCSWINSZ. - err := ioctlSetWinsize(fd, req, value) + err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } @@ -24,7 +36,30 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // The req value will usually be TCSETA or TIOCSETA. func IoctlSetTermios(fd int, req uint, value *Termios) error { // TODO: if we get the chance, remove the req parameter. - err := ioctlSetTermios(fd, req, value) + err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } + +// IoctlGetInt performs an ioctl operation which gets an integer value +// from fd, using the specified request number. +// +// A few ioctl requests use the return value as an output parameter; +// for those, IoctlRetInt should be used instead of this function. +func IoctlGetInt(fd int, req uint) (int, error) { + var value int + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return value, err +} + +func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { + var value Winsize + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return &value, err +} + +func IoctlGetTermios(fd int, req uint) (*Termios, error) { + var value Termios + err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + return &value, err +} diff --git a/vendor/golang.org/x/sys/unix/mkasm_darwin.go b/vendor/golang.org/x/sys/unix/mkasm_darwin.go new file mode 100644 index 000000000..4548b993d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mkasm_darwin.go @@ -0,0 +1,61 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go. +//This program must be run after mksyscall.go. +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "strings" +) + +func main() { + in1, err := ioutil.ReadFile("syscall_darwin.go") + if err != nil { + log.Fatalf("can't open syscall_darwin.go: %s", err) + } + arch := os.Args[1] + in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch)) + if err != nil { + log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err) + } + in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch)) + if err != nil { + log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err) + } + in := string(in1) + string(in2) + string(in3) + + trampolines := map[string]bool{} + + var out bytes.Buffer + + fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " ")) + fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n") + fmt.Fprintf(&out, "\n") + fmt.Fprintf(&out, "// +build go1.12\n") + fmt.Fprintf(&out, "\n") + fmt.Fprintf(&out, "#include \"textflag.h\"\n") + for _, line := range strings.Split(in, "\n") { + if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") { + continue + } + fn := line[5 : len(line)-13] + if !trampolines[fn] { + trampolines[fn] = true + fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn) + fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn) + } + } + err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644) + if err != nil { + log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err) + } +} diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 14624b953..67b84828a 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -60,6 +60,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ includes_Darwin=' includes_DragonFly=' #include #include +#include #include #include #include @@ -103,6 +105,7 @@ includes_FreeBSD=' #include #include #include +#include #include #include #include @@ -179,24 +182,31 @@ struct ltchars { #include #include #include +#include #include #include #include #include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include #include #include #include @@ -206,26 +216,23 @@ struct ltchars { #include #include #include +#include #include +#include #include #include +#include #include -#include #include #include -#include -#include -#include #include -#include -#include +#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include + #include #include @@ -264,6 +271,11 @@ struct ltchars { #define FS_KEY_DESC_PREFIX "fscrypt:" #define FS_KEY_DESC_PREFIX_SIZE 8 #define FS_MAX_KEY_SIZE 64 + +// The code generator produces -0x1 for (~0), but an unsigned value is necessary +// for the tipc_subscr timeout __u32 field. +#undef TIPC_WAIT_FOREVER +#define TIPC_WAIT_FOREVER 0xffffffff ' includes_NetBSD=' @@ -273,6 +285,7 @@ includes_NetBSD=' #include #include #include +#include #include #include #include @@ -299,6 +312,7 @@ includes_OpenBSD=' #include #include #include +#include #include #include #include @@ -335,6 +349,7 @@ includes_OpenBSD=' includes_SunOS=' #include #include +#include #include #include #include @@ -427,6 +442,7 @@ ccflags="$@" $2 == "XCASE" || $2 == "ALTWERASE" || $2 == "NOKERNINFO" || + $2 == "NFDBITS" || $2 ~ /^PAR/ || $2 ~ /^SIG[^_]/ || $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || @@ -451,6 +467,7 @@ ccflags="$@" $2 ~ /^SYSCTL_VERS/ || $2 !~ "MNT_BITS" && $2 ~ /^(MS|MNT|UMOUNT)_/ || + $2 ~ /^NS_GET_/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || $2 ~ /^KEXEC_/ || @@ -506,6 +523,7 @@ ccflags="$@" $2 ~ /^XDP_/ || $2 ~ /^(HDIO|WIN|SMART)_/ || $2 ~ /^CRYPTO_/ || + $2 ~ /^TIPC_/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || $2 ~/^PPPIOC/ || diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go new file mode 100644 index 000000000..eb4332059 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mkpost.go @@ -0,0 +1,122 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// mkpost processes the output of cgo -godefs to +// modify the generated types. It is used to clean up +// the sys API in an architecture specific manner. +// +// mkpost is run after cgo -godefs; see README.md. +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" + "os" + "regexp" +) + +func main() { + // Get the OS and architecture (using GOARCH_TARGET if it exists) + goos := os.Getenv("GOOS") + goarch := os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + // Check that we are using the Docker-based build system if we should be. + if goos == "linux" { + if os.Getenv("GOLANG_SYS_BUILD") != "docker" { + os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n") + os.Stderr.WriteString("See README.md\n") + os.Exit(1) + } + } + + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + log.Fatal(err) + } + + if goos == "aix" { + // Replace type of Atim, Mtim and Ctim by Timespec in Stat_t + // to avoid having both StTimespec and Timespec. + sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`) + b = sttimespec.ReplaceAll(b, []byte("Timespec")) + } + + // Intentionally export __val fields in Fsid and Sigset_t + valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`) + b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}")) + + // Intentionally export __fds_bits field in FdSet + fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`) + b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}")) + + // If we have empty Ptrace structs, we should delete them. Only s390x emits + // nonempty Ptrace structs. + ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`) + b = ptraceRexexp.ReplaceAll(b, nil) + + // Replace the control_regs union with a blank identifier for now. + controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`) + b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64")) + + // Remove fields that are added by glibc + // Note that this is unstable as the identifers are private. + removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`) + b = removeFieldsRegex.ReplaceAll(b, []byte("_")) + + // Convert [65]int8 to [65]byte in Utsname members to simplify + // conversion to string; see golang.org/issue/20753 + convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`) + b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte")) + + // Convert [1024]int8 to [1024]byte in Ptmget members + convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`) + b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte")) + + // Remove spare fields (e.g. in Statx_t) + spareFieldsRegex := regexp.MustCompile(`X__spare\S*`) + b = spareFieldsRegex.ReplaceAll(b, []byte("_")) + + // Remove cgo padding fields + removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) + b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) + + // Remove padding, hidden, or unused fields + removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`) + b = removeFieldsRegex.ReplaceAll(b, []byte("_")) + + // Remove the first line of warning from cgo + b = b[bytes.IndexByte(b, '\n')+1:] + // Modify the command in the header to include: + // mkpost, our own warning, and a build tag. + replacement := fmt.Sprintf(`$1 | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s,%s`, goarch, goos) + cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`) + b = cgoCommandRegex.ReplaceAll(b, []byte(replacement)) + + // Rename Stat_t time fields + if goos == "freebsd" && goarch == "386" { + // Hide Stat_t.[AMCB]tim_ext fields + renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`) + b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_")) + } + renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`) + b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}")) + + // gofmt + b, err = format.Source(b) + if err != nil { + log.Fatal(err) + } + + os.Stdout.Write(b) +} diff --git a/vendor/golang.org/x/sys/unix/mksyscall.go b/vendor/golang.org/x/sys/unix/mksyscall.go new file mode 100644 index 000000000..e4af9424e --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall.go @@ -0,0 +1,407 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_darwin.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named errno. + +A line beginning with //sysnb is like //sys, except that the +goroutine will not be suspended during the execution of the system +call. This must only be used for system calls which can never +block, as otherwise the system call could cause all goroutines to +hang. +*/ +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + plan9 = flag.Bool("plan9", false, "plan9") + openbsd = flag.Bool("openbsd", false, "openbsd") + netbsd = flag.Bool("netbsd", false, "netbsd") + dragonfly = flag.Bool("dragonfly", false, "dragonfly") + arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair + tags = flag.String("tags", "", "build tags") + filename = flag.String("output", "", "output file name (standard output if omitted)") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + // Get the OS and architecture (using GOARCH_TARGET if it exists) + goos := os.Getenv("GOOS") + if goos == "" { + fmt.Fprintln(os.Stderr, "GOOS not defined in environment") + os.Exit(1) + } + goarch := os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + + // Check that we are using the Docker-based build system if we should + if goos == "linux" { + if os.Getenv("GOLANG_SYS_BUILD") != "docker" { + fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n") + fmt.Fprintf(os.Stderr, "See README.md\n") + os.Exit(1) + } + } + + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + libc := false + if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") { + libc = true + } + trampolines := map[string]bool{} + + text := "" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, errno error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, sysname := f[2], f[3], f[4], f[5] + + // ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers. + if goos == "darwin" && !libc && funct == "ClockGettime" { + continue + } + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // Go function header. + outDecl := "" + if len(out) > 0 { + outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", ")) + } + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl) + + // Check if err return available + errvar := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + break + } + } + + // Prepare arguments to Syscall. + var args []string + n := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\tvar _p%d *byte\n", n) + text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name) + text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\tvar _p%d *byte\n", n) + text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass dummy pointer in that case. + // Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). + text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name) + text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n) + args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) + n++ + } else if p.Type == "int64" && (*openbsd || *netbsd) { + args = append(args, "0") + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else if endianness == "little-endian" { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } else if p.Type == "int64" && *dragonfly { + if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil { + args = append(args, "0") + } + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else if endianness == "little-endian" { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" { + if len(args)%2 == 1 && *arm { + // arm abi specifies 64-bit argument uses + // (even, odd) pair + args = append(args, "0") + } + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } + + // Determine which form to use; pad args with zeros. + asm := "Syscall" + if nonblock != nil { + if errvar == "" && goos == "linux" { + asm = "RawSyscallNoError" + } else { + asm = "RawSyscall" + } + } else { + if errvar == "" && goos == "linux" { + asm = "SyscallNoError" + } + } + if len(args) <= 3 { + for len(args) < 3 { + args = append(args, "0") + } + } else if len(args) <= 6 { + asm += "6" + for len(args) < 6 { + args = append(args, "0") + } + } else if len(args) <= 9 { + asm += "9" + for len(args) < 9 { + args = append(args, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct) + } + + // System call number. + if sysname == "" { + sysname = "SYS_" + funct + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToUpper(sysname) + } + + var libcFn string + if libc { + asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call + sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_ + sysname = strings.ToLower(sysname) // lowercase + if sysname == "getdirentries64" { + // Special case - libSystem name and + // raw syscall name don't match. + sysname = "__getdirentries64" + } + libcFn = sysname + sysname = "funcPC(libc_" + sysname + "_trampoline)" + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist) + + // Assign return values. + body := "" + ret := []string{"_", "_", "_"} + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" && !*plan9 { + reg = "e1" + ret[2] = reg + doErrno = true + } else if p.Name == "err" && *plan9 { + ret[0] = "r0" + ret[2] = "e1" + break + } else { + reg = fmt.Sprintf("r%d", i) + ret[i] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%s != 0", reg) + } + if p.Type == "int64" && endianness != "" { + // 64-bit number in r1:r0 or r0:r1. + if i+2 > len(out) { + fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct) + } + if endianness == "big-endian" { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) + } else { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) + } + ret[i] = fmt.Sprintf("r%d", i) + ret[i+1] = fmt.Sprintf("r%d", i+1) + } + if reg != "e1" || *plan9 { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { + text += fmt.Sprintf("\t%s\n", call) + } else { + if errvar == "" && goos == "linux" { + // raw syscall without error on Linux, see golang.org/issue/22924 + text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call) + } else { + text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) + } + } + text += body + + if *plan9 && ret[2] == "e1" { + text += "\tif int32(r0) == -1 {\n" + text += "\t\terr = e1\n" + text += "\t}\n" + } else if doErrno { + text += "\tif e1 != 0 {\n" + text += "\t\terr = errnoErr(e1)\n" + text += "\t}\n" + } + text += "\treturn\n" + text += "}\n\n" + + if libc && !trampolines[libcFn] { + // some system calls share a trampoline, like read and readlen. + trampolines[libcFn] = true + // Declare assembly trampoline. + text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn) + // Assembly trampoline calls the libc_* function, which this magic + // redirects to use the function from libSystem. + text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn) + text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn) + text += "\n" + } + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go new file mode 100644 index 000000000..3be3cdfc3 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go @@ -0,0 +1,415 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_aix.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt +*/ +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + aix = flag.Bool("aix", false, "aix") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + text := "" + cExtern := "/*\n#include \n#include \n" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // Check if value return, err return available + errvar := "" + retvar := "" + rettype := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + } else { + retvar = p.Name + rettype = p.Type + } + } + + // System call name. + if sysname == "" { + sysname = funct + } + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + cRettype := "" + if rettype == "unsafe.Pointer" { + cRettype = "uintptr_t" + } else if rettype == "uintptr" { + cRettype = "uintptr_t" + } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { + cRettype = "uintptr_t" + } else if rettype == "int" { + cRettype = "int" + } else if rettype == "int32" { + cRettype = "int" + } else if rettype == "int64" { + cRettype = "long long" + } else if rettype == "uint32" { + cRettype = "unsigned int" + } else if rettype == "uint64" { + cRettype = "unsigned long long" + } else { + cRettype = "int" + } + if sysname == "exit" { + cRettype = "void" + } + + // Change p.Types to c + var cIn []string + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "string" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t", "size_t") + } else if p.Type == "unsafe.Pointer" { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "uintptr" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "int" { + cIn = append(cIn, "int") + } else if p.Type == "int32" { + cIn = append(cIn, "int") + } else if p.Type == "int64" { + cIn = append(cIn, "long long") + } else if p.Type == "uint32" { + cIn = append(cIn, "unsigned int") + } else if p.Type == "uint64" { + cIn = append(cIn, "unsigned long long") + } else { + cIn = append(cIn, "int") + } + } + + if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + cExtern += "#define c_select select\n" + } + // Imports of system calls from libc + cExtern += fmt.Sprintf("%s %s", cRettype, sysname) + cIn := strings.Join(cIn, ", ") + cExtern += fmt.Sprintf("(%s);\n", cIn) + } + + // So file name. + if *aix { + if modname == "" { + modname = "libc.a/shr_64.o" + } else { + fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) + os.Exit(1) + } + } + + strconvfunc := "C.CString" + + // Go function header. + if outps != "" { + outps = fmt.Sprintf(" (%s)", outps) + } + if text != "" { + text += "\n" + } + + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) + + // Prepare arguments to Syscall. + var args []string + n := 0 + argN := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) + n++ + text += fmt.Sprintf("\tvar _p%d int\n", n) + text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) + args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + n++ + } else if p.Type == "bool" { + text += fmt.Sprintf("\tvar _p%d uint32\n", n) + text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) + args = append(args, fmt.Sprintf("_p%d", n)) + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "unsafe.Pointer" { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "int" { + if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { + args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) + } else if argN == 0 && funct == "fcntl" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := "" + if sysname == "exit" { + if errvar != "" { + call += "er :=" + } else { + call += "" + } + } else if errvar != "" { + call += "r0,er :=" + } else if retvar != "" { + call += "r0,_ :=" + } else { + call += "" + } + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist) + } else { + call += fmt.Sprintf("C.%s(%s)", sysname, arglist) + } + + // Assign return values. + body := "" + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + } else { + reg = "r0" + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + + // verify return + if sysname != "exit" && errvar != "" { + if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { + body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } else { + body += "\tif (r0 ==-1 && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + } else if errvar != "" { + body += "\tif (er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + + text += fmt.Sprintf("\t%s\n", call) + text += body + + text += "\treturn\n" + text += "}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + + +%s +*/ +import "C" +import ( + "unsafe" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go new file mode 100644 index 000000000..c96009951 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go @@ -0,0 +1,614 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_aix.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt + + +This program will generate three files and handle both gc and gccgo implementation: + - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) + - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 + - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. + + The generated code looks like this + +zsyscall_aix_ppc64.go +func asyscall(...) (n int, err error) { + // Pointer Creation + r1, e1 := callasyscall(...) + // Type Conversion + // Error Handler + return +} + +zsyscall_aix_ppc64_gc.go +//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" +//go:linkname libc_asyscall libc_asyscall +var asyscall syscallFunc + +func callasyscall(...) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) + return +} + +zsyscall_aix_ppc64_ggcgo.go + +// int asyscall(...) + +import "C" + +func callasyscall(...) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.asyscall(...)) + e1 = syscall.GetErrno() + return +} +*/ + +package main + +import ( + "bufio" + "flag" + "fmt" + "io/ioutil" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + aix = flag.Bool("aix", false, "aix") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + // GCCGO + textgccgo := "" + cExtern := "/*\n#include \n" + // GC + textgc := "" + dynimports := "" + linknames := "" + var vars []string + // COMMON + textcommon := "" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + if sysname == "" { + sysname = funct + } + + onlyCommon := false + if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" { + // This function call another syscall which is already implemented. + // Therefore, the gc and gccgo part must not be generated. + onlyCommon = true + } + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + + textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + if !onlyCommon { + textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + } + + // Check if value return, err return available + errvar := "" + rettype := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + } else { + rettype = p.Type + } + } + + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + // GCCGO Prototype return type + cRettype := "" + if rettype == "unsafe.Pointer" { + cRettype = "uintptr_t" + } else if rettype == "uintptr" { + cRettype = "uintptr_t" + } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { + cRettype = "uintptr_t" + } else if rettype == "int" { + cRettype = "int" + } else if rettype == "int32" { + cRettype = "int" + } else if rettype == "int64" { + cRettype = "long long" + } else if rettype == "uint32" { + cRettype = "unsigned int" + } else if rettype == "uint64" { + cRettype = "unsigned long long" + } else { + cRettype = "int" + } + if sysname == "exit" { + cRettype = "void" + } + + // GCCGO Prototype arguments type + var cIn []string + for i, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "string" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t", "size_t") + } else if p.Type == "unsafe.Pointer" { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "uintptr" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "int" { + if (i == 0 || i == 2) && funct == "fcntl" { + // These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock + cIn = append(cIn, "uintptr_t") + } else { + cIn = append(cIn, "int") + } + + } else if p.Type == "int32" { + cIn = append(cIn, "int") + } else if p.Type == "int64" { + cIn = append(cIn, "long long") + } else if p.Type == "uint32" { + cIn = append(cIn, "unsigned int") + } else if p.Type == "uint64" { + cIn = append(cIn, "unsigned long long") + } else { + cIn = append(cIn, "int") + } + } + + if !onlyCommon { + // GCCGO Prototype Generation + // Imports of system calls from libc + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + cExtern += "#define c_select select\n" + } + cExtern += fmt.Sprintf("%s %s", cRettype, sysname) + cIn := strings.Join(cIn, ", ") + cExtern += fmt.Sprintf("(%s);\n", cIn) + } + // GC Library name + if modname == "" { + modname = "libc.a/shr_64.o" + } else { + fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) + os.Exit(1) + } + sysvarname := fmt.Sprintf("libc_%s", sysname) + + if !onlyCommon { + // GC Runtime import of function to allow cross-platform builds. + dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname) + // GC Link symbol to proc address variable. + linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname) + // GC Library proc address variable. + vars = append(vars, sysvarname) + } + + strconvfunc := "BytePtrFromString" + strconvtype := "*byte" + + // Go function header. + if outps != "" { + outps = fmt.Sprintf(" (%s)", outps) + } + if textcommon != "" { + textcommon += "\n" + } + + textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) + + // Prepare arguments tocall. + var argscommon []string // Arguments in the common part + var argscall []string // Arguments for call prototype + var argsgc []string // Arguments for gc call (with syscall6) + var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall) + n := 0 + argN := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if p.Type == "string" && errvar != "" { + textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) + textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") + } else if p.Type == "bool" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if p.Type == "int" { + if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { + // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + + } else { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + nargs := len(argsgc) + + // COMMON function generation + argscommonlist := strings.Join(argscommon, ", ") + callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) + ret := []string{"_", "_"} + body := "" + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + ret[1] = reg + doErrno = true + } else { + reg = "r0" + ret[0] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%s != 0", reg) + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" { + textcommon += fmt.Sprintf("\t%s\n", callcommon) + } else { + textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) + } + textcommon += body + + if doErrno { + textcommon += "\tif e1 != 0 {\n" + textcommon += "\t\terr = errnoErr(e1)\n" + textcommon += "\t}\n" + } + textcommon += "\treturn\n" + textcommon += "}\n" + + if onlyCommon { + continue + } + + // CALL Prototype + callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) + + // GC function generation + asm := "syscall6" + if nonblock != nil { + asm = "rawSyscall6" + } + + if len(argsgc) <= 6 { + for len(argsgc) < 6 { + argsgc = append(argsgc, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) + os.Exit(1) + } + argsgclist := strings.Join(argsgc, ", ") + callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) + + textgc += callProto + textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) + textgc += "\treturn\n}\n" + + // GCCGO function generation + argsgccgolist := strings.Join(argsgccgo, ", ") + var callgccgo string + if sysname == "select" { + // select is a keyword of Go. Its name is + // changed to c_select. + callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist) + } else { + callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) + } + textgccgo += callProto + textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) + textgccgo += "\te1 = syscall.GetErrno()\n" + textgccgo += "\treturn\n}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + + // Print zsyscall_aix_ppc64.go + err := ioutil.WriteFile("zsyscall_aix_ppc64.go", + []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gc.go + vardecls := "\t" + strings.Join(vars, ",\n\t") + vardecls += " syscallFunc" + err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", + []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gccgo.go + err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", + []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } +} + +const srcTemplate1 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + +import ( + "unsafe" +) + + +%s + +%s +` +const srcTemplate2 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build !gccgo + +package %s + +import ( + "unsafe" +) +%s +%s +%s +type syscallFunc uintptr + +var ( +%s +) + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +%s +` +const srcTemplate3 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build gccgo + +package %s + +%s +*/ +import "C" +import ( + "syscall" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.go b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go new file mode 100644 index 000000000..3d864738b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_solaris.go @@ -0,0 +1,335 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* + This program reads a file containing function prototypes + (like syscall_solaris.go) and generates system call bodies. + The prototypes are marked by lines beginning with "//sys" + and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt +*/ + +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + text := "" + dynimports := "" + linknames := "" + var vars []string + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // So file name. + if modname == "" { + modname = "libc" + } + + // System call name. + if sysname == "" { + sysname = funct + } + + // System call pointer variable name. + sysvarname := fmt.Sprintf("proc%s", sysname) + + strconvfunc := "BytePtrFromString" + strconvtype := "*byte" + + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + // Runtime import of function to allow cross-platform builds. + dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname) + // Link symbol to proc address variable. + linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname) + // Library proc address variable. + vars = append(vars, sysvarname) + + // Go function header. + outlist := strings.Join(out, ", ") + if outlist != "" { + outlist = fmt.Sprintf(" (%s)", outlist) + } + if text != "" { + text += "\n" + } + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist) + + // Check if err return available + errvar := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + continue + } + } + + // Prepare arguments to Syscall. + var args []string + n := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name) + text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype) + text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n)) + n++ + } else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1]) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name)) + n++ + } else if p.Type == "int64" && endianness != "" { + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + } else if p.Type == "bool" { + text += fmt.Sprintf("\tvar _p%d uint32\n", n) + text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) + args = append(args, fmt.Sprintf("uintptr(_p%d)", n)) + n++ + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name)) + } + } + nargs := len(args) + + // Determine which form to use; pad args with zeros. + asm := "sysvicall6" + if nonblock != nil { + asm = "rawSysvicall6" + } + if len(args) <= 6 { + for len(args) < 6 { + args = append(args, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path) + os.Exit(1) + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist) + + // Assign return values. + body := "" + ret := []string{"_", "_", "_"} + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + ret[2] = reg + doErrno = true + } else { + reg = fmt.Sprintf("r%d", i) + ret[i] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%d != 0", reg) + } + if p.Type == "int64" && endianness != "" { + // 64-bit number in r1:r0 or r0:r1. + if i+2 > len(out) { + fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path) + os.Exit(1) + } + if endianness == "big-endian" { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1) + } else { + reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i) + } + ret[i] = fmt.Sprintf("r%d", i) + ret[i+1] = fmt.Sprintf("r%d", i+1) + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" { + text += fmt.Sprintf("\t%s\n", call) + } else { + text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call) + } + text += body + + if doErrno { + text += "\tif e1 != 0 {\n" + text += "\t\terr = e1\n" + text += "\t}\n" + } + text += "\treturn\n" + text += "}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + vardecls := "\t" + strings.Join(vars, ",\n\t") + vardecls += " syscallFunc" + fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + +import ( + "syscall" + "unsafe" +) +%s +%s +%s +var ( +%s +) + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go new file mode 100644 index 000000000..b6b409909 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksysctl_openbsd.go @@ -0,0 +1,355 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Parse the header files for OpenBSD and generate a Go usable sysctl MIB. +// +// Build a MIB with each entry being an array containing the level, type and +// a hash that will contain additional entries if the current entry is a node. +// We then walk this MIB and create a flattened sysctl name to OID hash. + +package main + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "regexp" + "sort" + "strings" +) + +var ( + goos, goarch string +) + +// cmdLine returns this programs's commandline arguments. +func cmdLine() string { + return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags. +func buildTags() string { + return fmt.Sprintf("%s,%s", goarch, goos) +} + +// reMatch performs regular expression match and stores the substring slice to value pointed by m. +func reMatch(re *regexp.Regexp, str string, m *[]string) bool { + *m = re.FindStringSubmatch(str) + if *m != nil { + return true + } + return false +} + +type nodeElement struct { + n int + t string + pE *map[string]nodeElement +} + +var ( + debugEnabled bool + mib map[string]nodeElement + node *map[string]nodeElement + nodeMap map[string]string + sysCtl []string +) + +var ( + ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`) + ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`) + ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`) + netInetRE = regexp.MustCompile(`^netinet/`) + netInet6RE = regexp.MustCompile(`^netinet6/`) + netRE = regexp.MustCompile(`^net/`) + bracesRE = regexp.MustCompile(`{.*}`) + ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`) + fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`) +) + +func debug(s string) { + if debugEnabled { + fmt.Fprintln(os.Stderr, s) + } +} + +// Walk the MIB and build a sysctl name to OID mapping. +func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) { + lNode := pNode // local copy of pointer to node + var keys []string + for k := range *lNode { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, key := range keys { + nodename := name + if name != "" { + nodename += "." + } + nodename += key + + nodeoid := append(oid, (*pNode)[key].n) + + if (*pNode)[key].t == `CTLTYPE_NODE` { + if _, ok := nodeMap[nodename]; ok { + lNode = &mib + ctlName := nodeMap[nodename] + for _, part := range strings.Split(ctlName, ".") { + lNode = ((*lNode)[part]).pE + } + } else { + lNode = (*pNode)[key].pE + } + buildSysctl(lNode, nodename, nodeoid) + } else if (*pNode)[key].t != "" { + oidStr := []string{} + for j := range nodeoid { + oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j])) + } + text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n" + sysCtl = append(sysCtl, text) + } + } +} + +func main() { + // Get the OS (using GOOS_TARGET if it exist) + goos = os.Getenv("GOOS_TARGET") + if goos == "" { + goos = os.Getenv("GOOS") + } + // Get the architecture (using GOARCH_TARGET if it exists) + goarch = os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + // Check if GOOS and GOARCH environment variables are defined + if goarch == "" || goos == "" { + fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") + os.Exit(1) + } + + mib = make(map[string]nodeElement) + headers := [...]string{ + `sys/sysctl.h`, + `sys/socket.h`, + `sys/tty.h`, + `sys/malloc.h`, + `sys/mount.h`, + `sys/namei.h`, + `sys/sem.h`, + `sys/shm.h`, + `sys/vmmeter.h`, + `uvm/uvmexp.h`, + `uvm/uvm_param.h`, + `uvm/uvm_swap_encrypt.h`, + `ddb/db_var.h`, + `net/if.h`, + `net/if_pfsync.h`, + `net/pipex.h`, + `netinet/in.h`, + `netinet/icmp_var.h`, + `netinet/igmp_var.h`, + `netinet/ip_ah.h`, + `netinet/ip_carp.h`, + `netinet/ip_divert.h`, + `netinet/ip_esp.h`, + `netinet/ip_ether.h`, + `netinet/ip_gre.h`, + `netinet/ip_ipcomp.h`, + `netinet/ip_ipip.h`, + `netinet/pim_var.h`, + `netinet/tcp_var.h`, + `netinet/udp_var.h`, + `netinet6/in6.h`, + `netinet6/ip6_divert.h`, + `netinet6/pim6_var.h`, + `netinet/icmp6.h`, + `netmpls/mpls.h`, + } + + ctls := [...]string{ + `kern`, + `vm`, + `fs`, + `net`, + //debug /* Special handling required */ + `hw`, + //machdep /* Arch specific */ + `user`, + `ddb`, + //vfs /* Special handling required */ + `fs.posix`, + `kern.forkstat`, + `kern.intrcnt`, + `kern.malloc`, + `kern.nchstats`, + `kern.seminfo`, + `kern.shminfo`, + `kern.timecounter`, + `kern.tty`, + `kern.watchdog`, + `net.bpf`, + `net.ifq`, + `net.inet`, + `net.inet.ah`, + `net.inet.carp`, + `net.inet.divert`, + `net.inet.esp`, + `net.inet.etherip`, + `net.inet.gre`, + `net.inet.icmp`, + `net.inet.igmp`, + `net.inet.ip`, + `net.inet.ip.ifq`, + `net.inet.ipcomp`, + `net.inet.ipip`, + `net.inet.mobileip`, + `net.inet.pfsync`, + `net.inet.pim`, + `net.inet.tcp`, + `net.inet.udp`, + `net.inet6`, + `net.inet6.divert`, + `net.inet6.ip6`, + `net.inet6.icmp6`, + `net.inet6.pim6`, + `net.inet6.tcp6`, + `net.inet6.udp6`, + `net.mpls`, + `net.mpls.ifq`, + `net.key`, + `net.pflow`, + `net.pfsync`, + `net.pipex`, + `net.rt`, + `vm.swapencrypt`, + //vfsgenctl /* Special handling required */ + } + + // Node name "fixups" + ctlMap := map[string]string{ + "ipproto": "net.inet", + "net.inet.ipproto": "net.inet", + "net.inet6.ipv6proto": "net.inet6", + "net.inet6.ipv6": "net.inet6.ip6", + "net.inet.icmpv6": "net.inet6.icmp6", + "net.inet6.divert6": "net.inet6.divert", + "net.inet6.tcp6": "net.inet.tcp", + "net.inet6.udp6": "net.inet.udp", + "mpls": "net.mpls", + "swpenc": "vm.swapencrypt", + } + + // Node mappings + nodeMap = map[string]string{ + "net.inet.ip.ifq": "net.ifq", + "net.inet.pfsync": "net.pfsync", + "net.mpls.ifq": "net.ifq", + } + + mCtls := make(map[string]bool) + for _, ctl := range ctls { + mCtls[ctl] = true + } + + for _, header := range headers { + debug("Processing " + header) + file, err := os.Open(filepath.Join("/usr/include", header)) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + var sub []string + if reMatch(ctlNames1RE, s.Text(), &sub) || + reMatch(ctlNames2RE, s.Text(), &sub) || + reMatch(ctlNames3RE, s.Text(), &sub) { + if sub[1] == `CTL_NAMES` { + // Top level. + node = &mib + } else { + // Node. + nodename := strings.ToLower(sub[2]) + ctlName := "" + if reMatch(netInetRE, header, &sub) { + ctlName = "net.inet." + nodename + } else if reMatch(netInet6RE, header, &sub) { + ctlName = "net.inet6." + nodename + } else if reMatch(netRE, header, &sub) { + ctlName = "net." + nodename + } else { + ctlName = nodename + ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) + } + + if val, ok := ctlMap[ctlName]; ok { + ctlName = val + } + if _, ok := mCtls[ctlName]; !ok { + debug("Ignoring " + ctlName + "...") + continue + } + + // Walk down from the top of the MIB. + node = &mib + for _, part := range strings.Split(ctlName, ".") { + if _, ok := (*node)[part]; !ok { + debug("Missing node " + part) + (*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} + } + node = (*node)[part].pE + } + } + + // Populate current node with entries. + i := -1 + for !strings.HasPrefix(s.Text(), "}") { + s.Scan() + if reMatch(bracesRE, s.Text(), &sub) { + i++ + } + if !reMatch(ctlTypeRE, s.Text(), &sub) { + continue + } + (*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} + } + } + } + err = s.Err() + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + file.Close() + } + buildSysctl(&mib, "", []int{}) + + sort.Strings(sysCtl) + text := strings.Join(sysCtl, "") + + fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) +} + +const srcTemplate = `// %s +// Code generated by the command above; DO NOT EDIT. + +// +build %s + +package unix + +type mibentry struct { + ctlname string + ctloid []_C_int +} + +var sysctlMib = []mibentry { +%s +} +` diff --git a/vendor/golang.org/x/sys/unix/mksysnum.go b/vendor/golang.org/x/sys/unix/mksysnum.go new file mode 100644 index 000000000..baa6ecd85 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksysnum.go @@ -0,0 +1,190 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Generate system call table for DragonFly, NetBSD, +// FreeBSD, OpenBSD or Darwin from master list +// (for example, /usr/src/sys/kern/syscalls.master or +// sys/syscall.h). +package main + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "regexp" + "strings" +) + +var ( + goos, goarch string +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksysnum.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return fmt.Sprintf("%s,%s", goarch, goos) +} + +func checkErr(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} + +// source string and substring slice for regexp +type re struct { + str string // source string + sub []string // matched sub-string +} + +// Match performs regular expression match +func (r *re) Match(exp string) bool { + r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str) + if r.sub != nil { + return true + } + return false +} + +// fetchFile fetches a text file from URL +func fetchFile(URL string) io.Reader { + resp, err := http.Get(URL) + checkErr(err) + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + checkErr(err) + return strings.NewReader(string(body)) +} + +// readFile reads a text file from path +func readFile(path string) io.Reader { + file, err := os.Open(os.Args[1]) + checkErr(err) + return file +} + +func format(name, num, proto string) string { + name = strings.ToUpper(name) + // There are multiple entries for enosys and nosys, so comment them out. + nm := re{str: name} + if nm.Match(`^SYS_E?NOSYS$`) { + name = fmt.Sprintf("// %s", name) + } + if name == `SYS_SYS_EXIT` { + name = `SYS_EXIT` + } + return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) +} + +func main() { + // Get the OS (using GOOS_TARGET if it exist) + goos = os.Getenv("GOOS_TARGET") + if goos == "" { + goos = os.Getenv("GOOS") + } + // Get the architecture (using GOARCH_TARGET if it exists) + goarch = os.Getenv("GOARCH_TARGET") + if goarch == "" { + goarch = os.Getenv("GOARCH") + } + // Check if GOOS and GOARCH environment variables are defined + if goarch == "" || goos == "" { + fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n") + os.Exit(1) + } + + file := strings.TrimSpace(os.Args[1]) + var syscalls io.Reader + if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") { + // Download syscalls.master file + syscalls = fetchFile(file) + } else { + syscalls = readFile(file) + } + + var text, line string + s := bufio.NewScanner(syscalls) + for s.Scan() { + t := re{str: line} + if t.Match(`^(.*)\\$`) { + // Handle continuation + line = t.sub[1] + line += strings.TrimLeft(s.Text(), " \t") + } else { + // New line + line = s.Text() + } + t = re{str: line} + if t.Match(`\\$`) { + continue + } + t = re{str: line} + + switch goos { + case "dragonfly": + if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) { + num, proto := t.sub[1], t.sub[2] + name := fmt.Sprintf("SYS_%s", t.sub[3]) + text += format(name, num, proto) + } + case "freebsd": + if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) { + num, proto := t.sub[1], t.sub[2] + name := fmt.Sprintf("SYS_%s", t.sub[3]) + text += format(name, num, proto) + } + case "openbsd": + if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) { + num, proto, name := t.sub[1], t.sub[3], t.sub[4] + text += format(name, num, proto) + } + case "netbsd": + if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) { + num, proto, compat := t.sub[1], t.sub[6], t.sub[8] + name := t.sub[7] + "_" + t.sub[9] + if t.sub[11] != "" { + name = t.sub[7] + "_" + t.sub[11] + } + name = strings.ToUpper(name) + if compat == "" || compat == "13" || compat == "30" || compat == "50" { + text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto) + } + } + case "darwin": + if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) { + name, num := t.sub[1], t.sub[2] + name = strings.ToUpper(name) + text += fmt.Sprintf(" SYS_%s = %s;\n", name, num) + } + default: + fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos) + os.Exit(1) + + } + } + err := s.Err() + checkErr(err) + + fmt.Printf(template, cmdLine(), buildTags(), text) +} + +const template = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package unix + +const( +%s)` diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index 1aa065f9c..9ad8a0d4a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -350,49 +350,12 @@ func (w WaitStatus) Signal() Signal { func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 } -func (w WaitStatus) CoreDump() bool { return w&0x200 != 0 } +func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 } func (w WaitStatus) TrapCause() int { return -1 } //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // There is no way to create a custom fcntl and to keep //sys fcntl easily, // Therefore, the programmer must call dup2 instead of fcntl in this case. diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go index bf05603f1..b3c8e3301 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go @@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go index 13d4321f4..9a6e02417 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go @@ -29,6 +29,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd.go b/vendor/golang.org/x/sys/unix/syscall_bsd.go index 97a8eef6f..3e6671426 100644 --- a/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -413,8 +413,6 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err e return kevent(kq, change, len(changes), event, len(events), timeout) } -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL - // sysctlmib translates name to mib number and appends any additional args. func sysctlmib(name string, args ...int) ([]_C_int, error) { // Translate name to mib number. diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 216b4ac9e..c5018a385 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -89,7 +89,6 @@ func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } @@ -340,43 +339,6 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} n := unsafe.Sizeof(uname.Sysname) @@ -498,7 +460,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go b/vendor/golang.org/x/sys/unix/syscall_darwin_386.go index 489726fa9..cf1bec6a3 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_386.go @@ -10,6 +10,9 @@ import ( "syscall" ) +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: int32(sec), Nsec: int32(nsec)} } @@ -43,6 +46,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index 914b89bde..5867ed00b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -10,6 +10,9 @@ import ( "syscall" ) +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} } @@ -43,6 +46,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go index 4a284cf50..e199e12a5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go @@ -8,6 +8,14 @@ import ( "syscall" ) +func ptrace(request int, pid int, addr uintptr, data uintptr) error { + return ENOTSUP +} + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + return ENOTSUP +} + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: int32(sec), Nsec: int32(nsec)} } @@ -41,6 +49,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index 52dcd88f6..2c50ca901 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -10,6 +10,14 @@ import ( "syscall" ) +func ptrace(request int, pid int, addr uintptr, data uintptr) error { + return ENOTSUP +} + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + return ENOTSUP +} + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} } @@ -43,6 +51,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 260a400f9..8c8d50297 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -14,6 +14,8 @@ package unix import "unsafe" +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL + // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { Len uint8 @@ -150,43 +152,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error { err := sysctl(mib, old, oldlen, nil, 0) if err != nil { @@ -325,7 +290,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go index 9babb31ea..a6b4830ac 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 329d240b9..25ac9340c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -36,6 +36,8 @@ var ( // INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h const _ino64First = 1200031 +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL + func supportsABI(ver uint32) bool { osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") }) return osreldate >= ver @@ -201,43 +203,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} n := unsafe.Sizeof(uname.Sysname) @@ -688,7 +653,7 @@ func PtraceSingleStep(pid int) (err error) { //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go index 21e03958c..dcc56457a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go index 9c945a657..321c3bace 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go index 5cd6243f2..697700831 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go index a31805487..dbbbfd603 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go @@ -33,6 +33,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 637b5017b..b2c2d9b2e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -71,6 +71,17 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { // ioctl itself should not be exposed directly, but additional get/set // functions for specific types are permissible. +// IoctlRetInt performs an ioctl operation specified by req on a device +// associated with opened file descriptor fd, and returns a non-negative +// integer that is returned by the ioctl syscall. +func IoctlRetInt(fd int, req uint) (int, error) { + ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0) + if err != 0 { + return 0, err + } + return int(ret), nil +} + // IoctlSetPointerInt performs an ioctl operation which sets an // integer value on fd, using the specified request number. The ioctl // argument is called with a pointer to the integer value, rather than @@ -80,52 +91,18 @@ func IoctlSetPointerInt(fd int, req uint, value int) error { return ioctl(fd, req, uintptr(unsafe.Pointer(&v))) } -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - func IoctlSetRTCTime(fd int, value *RTCTime) error { err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - func IoctlGetUint32(fd int, req uint) (uint32, error) { var value uint32 err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) return value, err } -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func IoctlGetRTCTime(fd int) (*RTCTime, error) { var value RTCTime err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) @@ -798,6 +775,70 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil } +// SockaddrTIPC implements the Sockaddr interface for AF_TIPC type sockets. +// For more information on TIPC, see: http://tipc.sourceforge.net/. +type SockaddrTIPC struct { + // Scope is the publication scopes when binding service/service range. + // Should be set to TIPC_CLUSTER_SCOPE or TIPC_NODE_SCOPE. + Scope int + + // Addr is the type of address used to manipulate a socket. Addr must be + // one of: + // - *TIPCSocketAddr: "id" variant in the C addr union + // - *TIPCServiceRange: "nameseq" variant in the C addr union + // - *TIPCServiceName: "name" variant in the C addr union + // + // If nil, EINVAL will be returned when the structure is used. + Addr TIPCAddr + + raw RawSockaddrTIPC +} + +// TIPCAddr is implemented by types that can be used as an address for +// SockaddrTIPC. It is only implemented by *TIPCSocketAddr, *TIPCServiceRange, +// and *TIPCServiceName. +type TIPCAddr interface { + tipcAddrtype() uint8 + tipcAddr() [12]byte +} + +func (sa *TIPCSocketAddr) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCSocketAddr{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCSocketAddr) tipcAddrtype() uint8 { return TIPC_SOCKET_ADDR } + +func (sa *TIPCServiceRange) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceRange{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCServiceRange) tipcAddrtype() uint8 { return TIPC_SERVICE_RANGE } + +func (sa *TIPCServiceName) tipcAddr() [12]byte { + var out [12]byte + copy(out[:], (*(*[unsafe.Sizeof(TIPCServiceName{})]byte)(unsafe.Pointer(sa)))[:]) + return out +} + +func (sa *TIPCServiceName) tipcAddrtype() uint8 { return TIPC_SERVICE_ADDR } + +func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Addr == nil { + return nil, 0, EINVAL + } + + sa.raw.Family = AF_TIPC + sa.raw.Scope = int8(sa.Scope) + sa.raw.Addrtype = sa.Addr.tipcAddrtype() + sa.raw.Addr = sa.Addr.tipcAddr() + + return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil +} + func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_NETLINK: @@ -923,6 +964,27 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { break } } + return sa, nil + case AF_TIPC: + pp := (*RawSockaddrTIPC)(unsafe.Pointer(rsa)) + + sa := &SockaddrTIPC{ + Scope: int(pp.Scope), + } + + // Determine which union variant is present in pp.Addr by checking + // pp.Addrtype. + switch pp.Addrtype { + case TIPC_SERVICE_RANGE: + sa.Addr = (*TIPCServiceRange)(unsafe.Pointer(&pp.Addr)) + case TIPC_SERVICE_ADDR: + sa.Addr = (*TIPCServiceName)(unsafe.Pointer(&pp.Addr)) + case TIPC_SOCKET_ADDR: + sa.Addr = (*TIPCSocketAddr)(unsafe.Pointer(&pp.Addr)) + default: + return nil, EINVAL + } + return sa, nil } return nil, EAFNOSUPPORT @@ -1160,6 +1222,34 @@ func KeyctlDHCompute(params *KeyctlDHParams, buffer []byte) (size int, err error return keyctlDH(KEYCTL_DH_COMPUTE, params, buffer) } +// KeyctlRestrictKeyring implements the KEYCTL_RESTRICT_KEYRING command. This +// command limits the set of keys that can be linked to the keyring, regardless +// of keyring permissions. The command requires the "setattr" permission. +// +// When called with an empty keyType the command locks the keyring, preventing +// any further keys from being linked to the keyring. +// +// The "asymmetric" keyType defines restrictions requiring key payloads to be +// DER encoded X.509 certificates signed by keys in another keyring. Restrictions +// for "asymmetric" include "builtin_trusted", "builtin_and_secondary_trusted", +// "key_or_keyring:", and "key_or_keyring::chain". +// +// As of Linux 4.12, only the "asymmetric" keyType defines type-specific +// restrictions. +// +// See the full documentation at: +// http://man7.org/linux/man-pages/man3/keyctl_restrict_keyring.3.html +// http://man7.org/linux/man-pages/man2/keyctl.2.html +func KeyctlRestrictKeyring(ringid int, keyType string, restriction string) error { + if keyType == "" { + return keyctlRestrictKeyring(KEYCTL_RESTRICT_KEYRING, ringid) + } + return keyctlRestrictKeyringByType(KEYCTL_RESTRICT_KEYRING, ringid, keyType, restriction) +} + +//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL +//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL + func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { var msg Msghdr var rsa RawSockaddrAny diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index e2f8cf6e5..e7fa665e6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -372,6 +372,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 87a30744d..088ce0f93 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -163,6 +163,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index f62679443..11930fc8f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -252,6 +252,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index cb20b15d5..251e2d971 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -180,6 +180,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index b3b21ec1e..7562fe97b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -208,6 +208,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 5144d4e13..a939ff8f2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -220,6 +220,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 0a100b66a..28d6d0f22 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -91,6 +91,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 6230f6405..6798c2625 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -179,6 +179,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index f81dbdc9c..eb5cb1a71 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -120,6 +120,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index b69565616..37321c12e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -107,6 +107,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 5ef309040..f95463ee2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -18,6 +18,8 @@ import ( "unsafe" ) +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL + // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { Len uint8 @@ -187,43 +189,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func IoctlGetPtmget(fd int, req uint) (*Ptmget, error) { var value Ptmget err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) @@ -365,7 +330,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go index 24f74e58c..24da8b524 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go index 6878bf7ff..25a0ac825 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go index dbbfcf71d..21591ecd4 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go index f3434465a..804749635 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 1a074b2fe..7fe65ef75 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -18,6 +18,8 @@ import ( "unsafe" ) +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL + // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { Len uint8 @@ -178,43 +180,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { //sys ioctl(fd int, req uint, arg uintptr) (err error) -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlSetInt performs an ioctl operation which sets an integer value -// on fd, using the specified request number. -func IoctlSetInt(fd int, req uint, value int) error { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) error { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -// IoctlGetInt performs an ioctl operation which gets an integer value -// from fd, using the specified request number. -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -340,7 +305,7 @@ func Uname(uname *Utsname) error { //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index d62da60d1..42b5a0e51 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go index 9a35334cb..6ea4b4883 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 5d812aaea..1c3d26fa2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go index 0fb39cf5e..a8c458cb0 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go @@ -28,6 +28,10 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = uint32(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 0153a316d..62f968c7f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -553,40 +553,10 @@ func Minor(dev uint64) uint32 { //sys ioctl(fd int, req uint, arg uintptr) (err error) -func IoctlSetInt(fd int, req uint, value int) (err error) { - return ioctl(fd, req, uintptr(value)) -} - -func ioctlSetWinsize(fd int, req uint, value *Winsize) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - -func ioctlSetTermios(fd int, req uint, value *Termios) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) -} - func IoctlSetTermio(fd int, req uint, value *Termio) (err error) { return ioctl(fd, req, uintptr(unsafe.Pointer(value))) } -func IoctlGetInt(fd int, req uint) (int, error) { - var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { - var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - -func IoctlGetTermios(fd int, req uint) (*Termios, error) { - var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return &value, err -} - func IoctlGetTermio(fd int, req uint) (*Termio, error) { var value Termio err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) @@ -679,7 +649,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek -//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sysnb Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go index 91c32ddf0..b22a34d7a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -18,6 +18,10 @@ func (iov *Iovec) SetLen(length int) { iov.Len = uint64(length) } +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/types_aix.go b/vendor/golang.org/x/sys/unix/types_aix.go new file mode 100644 index 000000000..40d2beede --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_aix.go @@ -0,0 +1,237 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore +// +build aix + +/* +Input to cgo -godefs. See also mkerrors.sh and mkall.sh +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong + PathMax = C.PATH_MAX +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +type off64 C.off64_t +type off C.off_t +type Mode_t C.mode_t + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +type Timex C.struct_timex + +type Time_t C.time_t + +type Tms C.struct_tms + +type Utimbuf C.struct_utimbuf + +type Timezone C.struct_timezone + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit64 + +type Pid_t C.pid_t + +type _Gid_t C.gid_t + +type dev_t C.dev_t + +// Files + +type Stat_t C.struct_stat + +type StatxTimestamp C.struct_statx_timestamp + +type Statx_t C.struct_statx + +type Dirent C.struct_dirent + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Cmsghdr C.struct_cmsghdr + +type ICMPv6Filter C.struct_icmp6_filter + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type Linger C.struct_linger + +type Msghdr C.struct_msghdr + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr +) + +type IfMsgHdr C.struct_if_msghdr + +// Misc + +type FdSet C.fd_set + +type Utsname C.struct_utsname + +type Ustat_t C.struct_ustat + +type Sigset_t C.sigset_t + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// Terminal handling + +type Termios C.struct_termios + +type Termio C.struct_termio + +type Winsize C.struct_winsize + +//poll + +type PollFd struct { + Fd int32 + Events uint16 + Revents uint16 +} + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +//flock_t + +type Flock_t C.struct_flock64 + +// Statfs + +type Fsid_t C.struct_fsid_t +type Fsid64_t C.struct_fsid64_t + +type Statfs_t C.struct_statfs + +const RNDGETENTCNT = 0x80045200 diff --git a/vendor/golang.org/x/sys/unix/types_darwin.go b/vendor/golang.org/x/sys/unix/types_darwin.go new file mode 100644 index 000000000..155c2e692 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_darwin.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define __DARWIN_UNIX03 0 +#define KERNEL +#define _DARWIN_USE_64_BIT_INODE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat64 + +type Statfs_t C.struct_statfs64 + +type Flock_t C.struct_flock + +type Fstore_t C.struct_fstore + +type Radvisory_t C.struct_radvisory + +type Fbootstraptransfer_t C.struct_fbootstraptransfer + +type Log2phys_t C.struct_log2phys + +type Fsid C.struct_fsid + +type Dirent C.struct_dirent + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet4Pktinfo C.struct_in_pktinfo + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfmaMsghdr2 C.struct_ifma_msghdr2 + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// uname + +type Utsname C.struct_utsname + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_dragonfly.go b/vendor/golang.org/x/sys/unix/types_dragonfly.go new file mode 100644 index 000000000..3365dd79d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_dragonfly.go @@ -0,0 +1,263 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.struct_fsid + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Uname + +type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go new file mode 100644 index 000000000..a121dc336 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_freebsd.go @@ -0,0 +1,400 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define _WANT_FREEBSD11_STAT 1 +#define _WANT_FREEBSD11_STATFS 1 +#define _WANT_FREEBSD11_DIRENT 1 +#define _WANT_FREEBSD11_KEVENT 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +// This structure is a duplicate of if_data on FreeBSD 8-STABLE. +// See /usr/include/net/if.h. +struct if_data8 { + u_char ifi_type; + u_char ifi_physical; + u_char ifi_addrlen; + u_char ifi_hdrlen; + u_char ifi_link_state; + u_char ifi_spare_char1; + u_char ifi_spare_char2; + u_char ifi_datalen; + u_long ifi_mtu; + u_long ifi_metric; + u_long ifi_baudrate; + u_long ifi_ipackets; + u_long ifi_ierrors; + u_long ifi_opackets; + u_long ifi_oerrors; + u_long ifi_collisions; + u_long ifi_ibytes; + u_long ifi_obytes; + u_long ifi_imcasts; + u_long ifi_omcasts; + u_long ifi_iqdrops; + u_long ifi_noproto; + u_long ifi_hwassist; +// FIXME: these are now unions, so maybe need to change definitions? +#undef ifi_epoch + time_t ifi_epoch; +#undef ifi_lastchange + struct timeval ifi_lastchange; +}; + +// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE. +// See /usr/include/net/if.h. +struct if_msghdr8 { + u_short ifm_msglen; + u_char ifm_version; + u_char ifm_type; + int ifm_addrs; + int ifm_flags; + u_short ifm_index; + struct if_data8 ifm_data; +}; +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +const ( + _statfsVersion = C.STATFS_VERSION + _dirblksiz = C.DIRBLKSIZ +) + +type Stat_t C.struct_stat + +type stat_freebsd11_t C.struct_freebsd11_stat + +type Statfs_t C.struct_statfs + +type statfs_freebsd11_t C.struct_freebsd11_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type dirent_freebsd11 C.struct_freebsd11_dirent + +type Fsid C.struct_fsid + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Advice to Fadvise + +const ( + FADV_NORMAL = C.POSIX_FADV_NORMAL + FADV_RANDOM = C.POSIX_FADV_RANDOM + FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL + FADV_WILLNEED = C.POSIX_FADV_WILLNEED + FADV_DONTNEED = C.POSIX_FADV_DONTNEED + FADV_NOREUSE = C.POSIX_FADV_NOREUSE +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPMreqn C.struct_ip_mreqn + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPMreqn = C.sizeof_struct_ip_mreqn + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_ATTACH = C.PT_ATTACH + PTRACE_CONT = C.PT_CONTINUE + PTRACE_DETACH = C.PT_DETACH + PTRACE_GETFPREGS = C.PT_GETFPREGS + PTRACE_GETFSBASE = C.PT_GETFSBASE + PTRACE_GETLWPLIST = C.PT_GETLWPLIST + PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS + PTRACE_GETREGS = C.PT_GETREGS + PTRACE_GETXSTATE = C.PT_GETXSTATE + PTRACE_IO = C.PT_IO + PTRACE_KILL = C.PT_KILL + PTRACE_LWPEVENTS = C.PT_LWP_EVENTS + PTRACE_LWPINFO = C.PT_LWPINFO + PTRACE_SETFPREGS = C.PT_SETFPREGS + PTRACE_SETREGS = C.PT_SETREGS + PTRACE_SINGLESTEP = C.PT_STEP + PTRACE_TRACEME = C.PT_TRACE_ME +) + +const ( + PIOD_READ_D = C.PIOD_READ_D + PIOD_WRITE_D = C.PIOD_WRITE_D + PIOD_READ_I = C.PIOD_READ_I + PIOD_WRITE_I = C.PIOD_WRITE_I +) + +const ( + PL_FLAG_BORN = C.PL_FLAG_BORN + PL_FLAG_EXITED = C.PL_FLAG_EXITED + PL_FLAG_SI = C.PL_FLAG_SI +) + +const ( + TRAP_BRKPT = C.TRAP_BRKPT + TRAP_TRACE = C.TRAP_TRACE +) + +type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo + +type __Siginfo C.struct___siginfo + +type Sigset_t C.sigset_t + +type Reg C.struct_reg + +type FpReg C.struct_fpreg + +type PtraceIoDesc C.struct_ptrace_io_desc + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent_freebsd11 + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + sizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 + sizeofIfData = C.sizeof_struct_if_data + SizeofIfData = C.sizeof_struct_if_data8 + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type ifMsghdr C.struct_if_msghdr + +type IfMsghdr C.struct_if_msghdr8 + +type ifData C.struct_if_data + +type IfData C.struct_if_data8 + +type IfaMsghdr C.struct_ifa_msghdr + +type IfmaMsghdr C.struct_ifma_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr + SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfZbuf C.struct_bpf_zbuf + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfZbufHeader C.struct_bpf_zbuf_header + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLINIGNEOF = C.POLLINIGNEOF + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Capabilities + +type CapRights C.struct_cap_rights + +// Uname + +type Utsname C.struct_utsname diff --git a/vendor/golang.org/x/sys/unix/types_netbsd.go b/vendor/golang.org/x/sys/unix/types_netbsd.go new file mode 100644 index 000000000..4a96d72c3 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_netbsd.go @@ -0,0 +1,290 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.fsid_t + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Advice to Fadvise + +const ( + FADV_NORMAL = C.POSIX_FADV_NORMAL + FADV_RANDOM = C.POSIX_FADV_RANDOM + FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL + FADV_WILLNEED = C.POSIX_FADV_WILLNEED + FADV_DONTNEED = C.POSIX_FADV_DONTNEED + FADV_NOREUSE = C.POSIX_FADV_NOREUSE +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +type Mclpool C.struct_mclpool + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfTimeval C.struct_bpf_timeval + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +type Ptmget C.struct_ptmget + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Sysctl + +type Sysctlnode C.struct_sysctlnode + +// Uname + +type Utsname C.struct_utsname + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go new file mode 100644 index 000000000..775cb57dc --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_openbsd.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Statfs_t C.struct_statfs + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +type Fsid C.fsid_t + +// File system limits + +const ( + PathMax = C.PATH_MAX +) + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Ptrace requests + +const ( + PTRACE_TRACEME = C.PT_TRACE_ME + PTRACE_CONT = C.PT_CONTINUE + PTRACE_KILL = C.PT_KILL +) + +// Events (kqueue, kevent) + +type Kevent_t C.struct_kevent + +// Select + +type FdSet C.fd_set + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type IfAnnounceMsghdr C.struct_if_announcemsghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +type Mclpool C.struct_mclpool + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfHdr C.struct_bpf_hdr + +type BpfTimeval C.struct_bpf_timeval + +// Terminal handling + +type Termios C.struct_termios + +type Winsize C.struct_winsize + +// fchmodat-like syscalls. + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW +) + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) + +// Signal Sets + +type Sigset_t C.sigset_t + +// Uname + +type Utsname C.struct_utsname + +// Uvmexp + +const SizeofUvmexp = C.sizeof_struct_uvmexp + +type Uvmexp C.struct_uvmexp + +// Clockinfo + +const SizeofClockinfo = C.sizeof_struct_clockinfo + +type Clockinfo C.struct_clockinfo diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go new file mode 100644 index 000000000..2b716f934 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/types_solaris.go @@ -0,0 +1,266 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +Input to cgo -godefs. See README.md +*/ + +// +godefs map struct_in_addr [4]byte /* in_addr */ +// +godefs map struct_in6_addr [16]byte /* in6_addr */ + +package unix + +/* +#define KERNEL +// These defines ensure that builds done on newer versions of Solaris are +// backwards-compatible with older versions of Solaris and +// OpenSolaris-based derivatives. +#define __USE_SUNOS_SOCKETS__ // msghdr +#define __USE_LEGACY_PROTOTYPES__ // iovec +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +union sockaddr_all { + struct sockaddr s1; // this one gets used for fields + struct sockaddr_in s2; // these pad it out + struct sockaddr_in6 s3; + struct sockaddr_un s4; + struct sockaddr_dl s5; +}; + +struct sockaddr_any { + struct sockaddr addr; + char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; +}; + +*/ +import "C" + +// Machine characteristics + +const ( + SizeofPtr = C.sizeofPtr + SizeofShort = C.sizeof_short + SizeofInt = C.sizeof_int + SizeofLong = C.sizeof_long + SizeofLongLong = C.sizeof_longlong + PathMax = C.PATH_MAX + MaxHostNameLen = C.MAXHOSTNAMELEN +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +// Time + +type Timespec C.struct_timespec + +type Timeval C.struct_timeval + +type Timeval32 C.struct_timeval32 + +type Tms C.struct_tms + +type Utimbuf C.struct_utimbuf + +// Processes + +type Rusage C.struct_rusage + +type Rlimit C.struct_rlimit + +type _Gid_t C.gid_t + +// Files + +type Stat_t C.struct_stat + +type Flock_t C.struct_flock + +type Dirent C.struct_dirent + +// Filesystems + +type _Fsblkcnt_t C.fsblkcnt_t + +type Statvfs_t C.struct_statvfs + +// Sockets + +type RawSockaddrInet4 C.struct_sockaddr_in + +type RawSockaddrInet6 C.struct_sockaddr_in6 + +type RawSockaddrUnix C.struct_sockaddr_un + +type RawSockaddrDatalink C.struct_sockaddr_dl + +type RawSockaddr C.struct_sockaddr + +type RawSockaddrAny C.struct_sockaddr_any + +type _Socklen C.socklen_t + +type Linger C.struct_linger + +type Iovec C.struct_iovec + +type IPMreq C.struct_ip_mreq + +type IPv6Mreq C.struct_ipv6_mreq + +type Msghdr C.struct_msghdr + +type Cmsghdr C.struct_cmsghdr + +type Inet6Pktinfo C.struct_in6_pktinfo + +type IPv6MTUInfo C.struct_ip6_mtuinfo + +type ICMPv6Filter C.struct_icmp6_filter + +const ( + SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in + SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 + SizeofSockaddrAny = C.sizeof_struct_sockaddr_any + SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un + SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofLinger = C.sizeof_struct_linger + SizeofIPMreq = C.sizeof_struct_ip_mreq + SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq + SizeofMsghdr = C.sizeof_struct_msghdr + SizeofCmsghdr = C.sizeof_struct_cmsghdr + SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo + SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo + SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter +) + +// Select + +type FdSet C.fd_set + +// Misc + +type Utsname C.struct_utsname + +type Ustat_t C.struct_ustat + +const ( + AT_FDCWD = C.AT_FDCWD + AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW + AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW + AT_REMOVEDIR = C.AT_REMOVEDIR + AT_EACCESS = C.AT_EACCESS +) + +// Routing and interface messages + +const ( + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics +) + +type IfMsghdr C.struct_if_msghdr + +type IfData C.struct_if_data + +type IfaMsghdr C.struct_ifa_msghdr + +type RtMsghdr C.struct_rt_msghdr + +type RtMetrics C.struct_rt_metrics + +// Berkeley packet filter + +const ( + SizeofBpfVersion = C.sizeof_struct_bpf_version + SizeofBpfStat = C.sizeof_struct_bpf_stat + SizeofBpfProgram = C.sizeof_struct_bpf_program + SizeofBpfInsn = C.sizeof_struct_bpf_insn + SizeofBpfHdr = C.sizeof_struct_bpf_hdr +) + +type BpfVersion C.struct_bpf_version + +type BpfStat C.struct_bpf_stat + +type BpfProgram C.struct_bpf_program + +type BpfInsn C.struct_bpf_insn + +type BpfTimeval C.struct_bpf_timeval + +type BpfHdr C.struct_bpf_hdr + +// Terminal handling + +type Termios C.struct_termios + +type Termio C.struct_termio + +type Winsize C.struct_winsize + +// poll + +type PollFd C.struct_pollfd + +const ( + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLIN = C.POLLIN + POLLNVAL = C.POLLNVAL + POLLOUT = C.POLLOUT + POLLPRI = C.POLLPRI + POLLRDBAND = C.POLLRDBAND + POLLRDNORM = C.POLLRDNORM + POLLWRBAND = C.POLLWRBAND + POLLWRNORM = C.POLLWRNORM +) diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go index 3b39d7408..6217cdba5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go @@ -3,7 +3,7 @@ // +build 386,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index 8fe554777..e3ff2ee3d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -3,7 +3,7 @@ // +build amd64,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go index 7a977770d..3e417571a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go @@ -3,7 +3,7 @@ // +build arm,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index 6d56d8a05..cbd8ed18b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -3,7 +3,7 @@ // +build arm64,darwin -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -980,6 +980,7 @@ const ( NET_RT_MAXID = 0xa NET_RT_STAT = 0x4 NET_RT_TRASH = 0x5 + NFDBITS = 0x20 NL0 = 0x0 NL1 = 0x100 NL2 = 0x200 diff --git a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index bbe6089bb..613047174 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -938,6 +938,7 @@ const ( NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 NET_RT_MAXID = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index d2bbaabc8..b72544fcd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -3,7 +3,7 @@ // +build 386,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -1055,6 +1055,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index 4f8db783d..9f382678e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1056,6 +1056,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index 53e5de605..16db56abc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -3,7 +3,7 @@ // +build arm,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go package unix @@ -1063,6 +1063,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index d4a192fef..1a1de3454 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -3,7 +3,7 @@ // +build arm64,freebsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1056,6 +1056,7 @@ const ( NET_RT_IFLIST = 0x3 NET_RT_IFLISTL = 0x5 NET_RT_IFMALIST = 0x4 + NFDBITS = 0x40 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 5213d820a..fcf5796a0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -722,6 +726,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -987,6 +992,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1085,6 +1091,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1097,6 +1114,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1342,6 +1361,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1406,6 +1426,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1695,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1686,6 +1712,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1724,6 +1751,10 @@ const ( PTRACE_SINGLEBLOCK = 0x21 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 @@ -1784,7 +1815,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1888,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1913,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1921,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1933,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1942,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2028,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2168,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2432,6 +2469,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2445,7 +2547,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2644,6 +2746,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2660,6 +2764,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 39b630cc5..5bcf3dbd7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -722,6 +726,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -987,6 +992,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1085,6 +1091,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1097,6 +1114,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1342,6 +1361,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1406,6 +1426,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1672,6 +1696,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1687,6 +1713,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1725,6 +1752,10 @@ const ( PTRACE_SINGLEBLOCK = 0x21 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 @@ -1785,7 +1816,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1858,6 +1889,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1882,6 +1914,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1889,7 +1922,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1901,6 +1934,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1909,8 +1943,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1995,6 +2029,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2133,6 +2169,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2433,6 +2470,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2446,7 +2548,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2644,6 +2746,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2660,6 +2764,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index c59a1beb3..3e02dcff8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1716,7 @@ const ( PTRACE_GETSIGMASK = 0x420a PTRACE_GETVFPREGS = 0x1b PTRACE_GETWMMXREGS = 0x12 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x16 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1730,6 +1757,10 @@ const ( PTRACE_SET_SYSCALL = 0x17 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 PT_DATA_ADDR = 0x10004 PT_TEXT_ADDR = 0x10000 @@ -1791,7 +1822,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1864,6 +1895,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1888,6 +1920,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1895,7 +1928,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1907,6 +1940,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1915,8 +1949,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2001,6 +2035,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2139,6 +2175,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2439,6 +2476,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2452,7 +2554,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2650,6 +2752,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2666,6 +2770,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 5f35c19d1..2293f8bb8 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -561,6 +564,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -724,6 +728,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -989,6 +994,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1087,6 +1093,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1099,6 +1116,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1343,6 +1362,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1407,6 +1427,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1672,6 +1696,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1685,6 +1711,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1717,6 +1744,12 @@ const ( PTRACE_SETSIGMASK = 0x420b PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 + PTRACE_SYSEMU = 0x1f + PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1775,7 +1808,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1848,6 +1881,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1872,6 +1906,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1879,7 +1914,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1891,6 +1926,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1899,8 +1935,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1985,6 +2021,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2123,6 +2161,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2424,6 +2463,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2437,7 +2541,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2635,6 +2739,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2651,6 +2757,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 7f1b7bef2..57742ea27 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1709,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1753,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1815,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1888,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1913,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1921,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1933,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1942,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2028,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2168,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2471,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2549,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2748,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2766,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 603d88b8b..33bfa6cbf 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1709,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1753,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1815,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1888,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1913,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1921,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1933,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1942,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2028,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2168,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2471,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2549,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2748,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2766,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ed178f8a7..89fd414e6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1709,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1753,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1815,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1888,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1913,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1921,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1933,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1942,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2028,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2168,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2471,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2549,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2748,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2766,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 080b78933..aabe5e424 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x20 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1683,6 +1709,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 PTRACE_GET_WATCH_REGS = 0xd0 @@ -1726,6 +1753,10 @@ const ( PTRACE_SET_WATCH_REGS = 0xd1 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1784,7 +1815,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1857,6 +1888,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1881,6 +1913,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1888,7 +1921,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1900,6 +1933,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1908,8 +1942,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1994,6 +2028,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2132,6 +2168,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2434,6 +2471,71 @@ const ( TIOCSTI = 0x5472 TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x8000 TPACKET_ALIGNMENT = 0x10 @@ -2447,7 +2549,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2646,6 +2748,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2662,6 +2766,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 961e8eabe..272279128 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1339,6 +1358,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1405,6 +1425,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80000000 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1695,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1716,7 @@ const ( PTRACE_GETVRREGS = 0x12 PTRACE_GETVSRREGS = 0x1b PTRACE_GET_DEBUGREG = 0x19 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1756,10 @@ const ( PTRACE_SINGLEBLOCK = 0x100 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1d PTRACE_SYSEMU_SINGLESTEP = 0x1e PTRACE_TRACEME = 0x0 @@ -1842,7 +1873,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1915,6 +1946,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1939,6 +1971,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1946,7 +1979,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1958,6 +1991,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1966,8 +2000,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2052,6 +2086,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2190,6 +2226,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2494,6 +2531,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x400000 TPACKET_ALIGNMENT = 0x10 @@ -2507,7 +2609,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2705,6 +2807,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2721,6 +2825,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0xc00 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 6e0538f22..e33be416c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1339,6 +1358,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1405,6 +1425,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80000000 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1695,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1716,7 @@ const ( PTRACE_GETVRREGS = 0x12 PTRACE_GETVSRREGS = 0x1b PTRACE_GET_DEBUGREG = 0x19 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1756,10 @@ const ( PTRACE_SINGLEBLOCK = 0x100 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_SYSEMU = 0x1d PTRACE_SYSEMU_SINGLESTEP = 0x1e PTRACE_TRACEME = 0x0 @@ -1842,7 +1873,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1915,6 +1946,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1939,6 +1971,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1946,7 +1979,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1958,6 +1991,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1966,8 +2000,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2052,6 +2086,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2190,6 +2226,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2494,6 +2531,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x400000 TPACKET_ALIGNMENT = 0x10 @@ -2507,7 +2609,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2705,6 +2807,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2721,6 +2825,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0xc00 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 06c0148c1..b9908d309 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1669,6 +1693,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1682,6 +1708,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1714,6 +1741,10 @@ const ( PTRACE_SETSIGMASK = 0x420b PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 @@ -1772,7 +1803,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1845,6 +1876,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1869,6 +1901,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1876,7 +1909,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1888,6 +1921,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1896,8 +1930,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -1982,6 +2016,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2120,6 +2156,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2420,6 +2457,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2433,7 +2535,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2631,6 +2733,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2647,6 +2751,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 39875095c..85647f4f7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -253,6 +253,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -304,9 +305,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -460,6 +462,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -560,6 +563,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -721,6 +725,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x0 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -986,6 +991,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1084,6 +1090,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1096,6 +1113,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1340,6 +1359,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1404,6 +1424,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_USERNS = 0xb701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1671,6 +1695,8 @@ const ( PTRACE_DETACH = 0x11 PTRACE_DISABLE_TE = 0x5010 PTRACE_ENABLE_TE = 0x5009 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1685,6 +1711,7 @@ const ( PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a PTRACE_GET_LAST_BREAK = 0x5006 + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1728,6 +1755,10 @@ const ( PTRACE_SINGLEBLOCK = 0xc PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TE_ABORT_RAND = 0x5011 PTRACE_TRACEME = 0x0 PT_ACR0 = 0x90 @@ -1845,7 +1876,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1918,6 +1949,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1942,6 +1974,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1949,7 +1982,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1961,6 +1994,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1969,8 +2003,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2055,6 +2089,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2193,6 +2229,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x44 SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2493,6 +2530,71 @@ const ( TIOCSTI = 0x5412 TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2506,7 +2608,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2704,6 +2806,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2720,6 +2824,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 8d80f99bc..c0095a543 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -256,6 +256,7 @@ const ( BPF_F_STACK_BUILD_ID = 0x20 BPF_F_STRICT_ALIGNMENT = 0x1 BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TUNINFO_IPV6 = 0x1 BPF_F_USER_BUILD_ID = 0x800 BPF_F_USER_STACK = 0x100 @@ -307,9 +308,10 @@ const ( BPF_RET = 0x6 BPF_RSH = 0x70 BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 BPF_STX = 0x3 @@ -463,6 +465,7 @@ const ( DAXFS_MAGIC = 0x64646178 DEBUGFS_MAGIC = 0x64626720 DEVPTS_SUPER_MAGIC = 0x1cd1 + DMA_BUF_MAGIC = 0x444d4142 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -564,6 +567,7 @@ const ( ETH_P_IRDA = 0x17 ETH_P_LAT = 0x6004 ETH_P_LINK_CTL = 0x886c + ETH_P_LLDP = 0x88cc ETH_P_LOCALTALK = 0x9 ETH_P_LOOP = 0x60 ETH_P_LOOPBACK = 0x9000 @@ -725,6 +729,7 @@ const ( F_OFD_SETLKW = 0x26 F_OK = 0x0 F_RDLCK = 0x1 + F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 F_SEAL_SHRINK = 0x2 @@ -990,6 +995,7 @@ const ( IPV6_RECVRTHDR = 0x38 IPV6_RECVTCLASS = 0x42 IPV6_ROUTER_ALERT = 0x16 + IPV6_ROUTER_ALERT_ISOLATE = 0x1e IPV6_RTHDR = 0x39 IPV6_RTHDRDSTOPTS = 0x37 IPV6_RTHDR_LOOSE = 0x0 @@ -1088,6 +1094,17 @@ const ( KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 KEYCTL_ASSUME_AUTHORITY = 0x10 + KEYCTL_CAPABILITIES = 0x1f + KEYCTL_CAPS0_BIG_KEY = 0x10 + KEYCTL_CAPS0_CAPABILITIES = 0x1 + KEYCTL_CAPS0_DIFFIE_HELLMAN = 0x4 + KEYCTL_CAPS0_INVALIDATE = 0x20 + KEYCTL_CAPS0_MOVE = 0x80 + KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 + KEYCTL_CAPS0_PUBLIC_KEY = 0x8 + KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 + KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 KEYCTL_CLEAR = 0x7 KEYCTL_DESCRIBE = 0x6 @@ -1100,6 +1117,8 @@ const ( KEYCTL_INVALIDATE = 0x15 KEYCTL_JOIN_SESSION_KEYRING = 0x1 KEYCTL_LINK = 0x8 + KEYCTL_MOVE = 0x1e + KEYCTL_MOVE_EXCL = 0x1 KEYCTL_NEGATE = 0xd KEYCTL_PKEY_DECRYPT = 0x1a KEYCTL_PKEY_ENCRYPT = 0x19 @@ -1344,6 +1363,7 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFDBITS = 0x40 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1408,6 +1428,10 @@ const ( NLM_F_ROOT = 0x100 NOFLSH = 0x80 NSFS_MAGIC = 0x6e736673 + NS_GET_NSTYPE = 0x2000b703 + NS_GET_OWNER_UID = 0x2000b704 + NS_GET_PARENT = 0x2000b702 + NS_GET_USERNS = 0x2000b701 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1673,6 +1697,8 @@ const ( PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 + PTRACE_EVENTMSG_SYSCALL_ENTRY = 0x1 + PTRACE_EVENTMSG_SYSCALL_EXIT = 0x2 PTRACE_EVENT_CLONE = 0x3 PTRACE_EVENT_EXEC = 0x4 PTRACE_EVENT_EXIT = 0x6 @@ -1690,6 +1716,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1729,6 +1756,10 @@ const ( PTRACE_SINGLESTEP = 0x9 PTRACE_SPARC_DETACH = 0xb PTRACE_SYSCALL = 0x18 + PTRACE_SYSCALL_INFO_ENTRY = 0x1 + PTRACE_SYSCALL_INFO_EXIT = 0x2 + PTRACE_SYSCALL_INFO_NONE = 0x0 + PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 PTRACE_WRITEDATA = 0x11 PTRACE_WRITETEXT = 0x13 @@ -1837,7 +1868,7 @@ const ( RTAX_UNSPEC = 0x0 RTAX_WINDOW = 0x3 RTA_ALIGNTO = 0x4 - RTA_MAX = 0x1d + RTA_MAX = 0x1e RTCF_DIRECTSRC = 0x4000000 RTCF_DOREDIRECT = 0x1000000 RTCF_LOG = 0x2000000 @@ -1910,6 +1941,7 @@ const ( RTM_DELMDB = 0x55 RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 + RTM_DELNEXTHOP = 0x69 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -1934,6 +1966,7 @@ const ( RTM_GETNEIGH = 0x1e RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 + RTM_GETNEXTHOP = 0x6a RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1941,7 +1974,7 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x67 + RTM_MAX = 0x6b RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -1953,6 +1986,7 @@ const ( RTM_NEWNEIGH = 0x1c RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 + RTM_NEWNEXTHOP = 0x68 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1961,8 +1995,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x16 - RTM_NR_MSGTYPES = 0x58 + RTM_NR_FAMILIES = 0x17 + RTM_NR_MSGTYPES = 0x5c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2047,6 +2081,8 @@ const ( SIOCDRARP = 0x8960 SIOCETHTOOL = 0x8946 SIOCGARP = 0x8954 + SIOCGETLINKNAME = 0x89e0 + SIOCGETNODEID = 0x89e1 SIOCGHWTSTAMP = 0x89b1 SIOCGIFADDR = 0x8915 SIOCGIFBR = 0x8940 @@ -2185,6 +2221,7 @@ const ( SO_DEBUG = 0x1 SO_DETACH_BPF = 0x1b SO_DETACH_FILTER = 0x1b + SO_DETACH_REUSEPORT_BPF = 0x47 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_EE_CODE_TXTIME_INVALID_PARAM = 0x1 @@ -2482,6 +2519,71 @@ const ( TIOCSTOP = 0x2000746f TIOCSWINSZ = 0x80087467 TIOCVHANGUP = 0x20005437 + TIPC_ADDR_ID = 0x3 + TIPC_ADDR_MCAST = 0x1 + TIPC_ADDR_NAME = 0x2 + TIPC_ADDR_NAMESEQ = 0x1 + TIPC_CFG_SRV = 0x0 + TIPC_CLUSTER_BITS = 0xc + TIPC_CLUSTER_MASK = 0xfff000 + TIPC_CLUSTER_OFFSET = 0xc + TIPC_CLUSTER_SIZE = 0xfff + TIPC_CONN_SHUTDOWN = 0x5 + TIPC_CONN_TIMEOUT = 0x82 + TIPC_CRITICAL_IMPORTANCE = 0x3 + TIPC_DESTNAME = 0x3 + TIPC_DEST_DROPPABLE = 0x81 + TIPC_ERRINFO = 0x1 + TIPC_ERR_NO_NAME = 0x1 + TIPC_ERR_NO_NODE = 0x3 + TIPC_ERR_NO_PORT = 0x2 + TIPC_ERR_OVERLOAD = 0x4 + TIPC_GROUP_JOIN = 0x87 + TIPC_GROUP_LEAVE = 0x88 + TIPC_GROUP_LOOPBACK = 0x1 + TIPC_GROUP_MEMBER_EVTS = 0x2 + TIPC_HIGH_IMPORTANCE = 0x2 + TIPC_IMPORTANCE = 0x7f + TIPC_LINK_STATE = 0x2 + TIPC_LOW_IMPORTANCE = 0x0 + TIPC_MAX_BEARER_NAME = 0x20 + TIPC_MAX_IF_NAME = 0x10 + TIPC_MAX_LINK_NAME = 0x44 + TIPC_MAX_MEDIA_NAME = 0x10 + TIPC_MAX_USER_MSG_SIZE = 0x101d0 + TIPC_MCAST_BROADCAST = 0x85 + TIPC_MCAST_REPLICAST = 0x86 + TIPC_MEDIUM_IMPORTANCE = 0x1 + TIPC_NODEID_LEN = 0x10 + TIPC_NODE_BITS = 0xc + TIPC_NODE_MASK = 0xfff + TIPC_NODE_OFFSET = 0x0 + TIPC_NODE_RECVQ_DEPTH = 0x83 + TIPC_NODE_SIZE = 0xfff + TIPC_NODE_STATE = 0x0 + TIPC_OK = 0x0 + TIPC_PUBLISHED = 0x1 + TIPC_RESERVED_TYPES = 0x40 + TIPC_RETDATA = 0x2 + TIPC_SERVICE_ADDR = 0x2 + TIPC_SERVICE_RANGE = 0x1 + TIPC_SOCKET_ADDR = 0x3 + TIPC_SOCK_RECVQ_DEPTH = 0x84 + TIPC_SOCK_RECVQ_USED = 0x89 + TIPC_SRC_DROPPABLE = 0x80 + TIPC_SUBSCR_TIMEOUT = 0x3 + TIPC_SUB_CANCEL = 0x4 + TIPC_SUB_PORTS = 0x1 + TIPC_SUB_SERVICE = 0x2 + TIPC_TOP_SRV = 0x1 + TIPC_WAIT_FOREVER = 0xffffffff + TIPC_WITHDRAWN = 0x2 + TIPC_ZONE_BITS = 0x8 + TIPC_ZONE_CLUSTER_MASK = 0xfffff000 + TIPC_ZONE_MASK = 0xff000000 + TIPC_ZONE_OFFSET = 0x18 + TIPC_ZONE_SCOPE = 0x1 + TIPC_ZONE_SIZE = 0xff TMPFS_MAGIC = 0x1021994 TOSTOP = 0x100 TPACKET_ALIGNMENT = 0x10 @@ -2495,7 +2597,7 @@ const ( TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 TP_STATUS_SEND_REQUEST = 0x1 - TP_STATUS_TS_RAW_HARDWARE = -0x80000000 + TP_STATUS_TS_RAW_HARDWARE = 0x80000000 TP_STATUS_TS_SOFTWARE = 0x20000000 TP_STATUS_TS_SYS_HARDWARE = 0x40000000 TP_STATUS_USER = 0x1 @@ -2693,6 +2795,8 @@ const ( XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 + XDP_OPTIONS = 0x8 + XDP_OPTIONS_ZEROCOPY = 0x1 XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 @@ -2709,6 +2813,7 @@ const ( XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 XTABS = 0x1800 + Z3FOLD_MAGIC = 0x33 ZSMALLOC_MAGIC = 0x58295829 __TIOCFLUSH = 0x80047410 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go index 78cc04ea6..96b9b8ab3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -3,7 +3,7 @@ // +build 386,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -1085,6 +1085,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index 92185e693..ed522a84e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1075,6 +1075,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go index 373ad4543..c8d36fe99 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -3,7 +3,7 @@ // +build arm,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -marm _const.go package unix @@ -1065,6 +1065,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go index fb6c60441..f1c146a74 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go @@ -3,7 +3,7 @@ // +build arm64,netbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -1075,6 +1075,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_OIFLIST = 0x4 NET_RT_OOIFLIST = 0x3 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index d8be04518..4faf7894b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -3,7 +3,7 @@ // +build 386,openbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go package unix @@ -946,6 +946,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index 1f9e8a29e..c2259316f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -3,7 +3,7 @@ // +build amd64,openbsd -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -990,6 +990,7 @@ const ( NET_RT_MAXID = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 79d5695c3..ac56a9073 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -1,7 +1,7 @@ // mkerrors.sh // Code generated by the command above; see README.md. DO NOT EDIT. -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go // +build arm,openbsd @@ -947,6 +947,7 @@ const ( NET_RT_MAXID = 0x6 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go index ec5f92de8..1792d3f13 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go @@ -996,6 +996,7 @@ const ( NET_RT_MAXID = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 + NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 22569db31..46e054ccb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -3,7 +3,7 @@ // +build amd64,solaris -// Created by cgo -godefs - DO NOT EDIT +// Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go package unix @@ -666,6 +666,7 @@ const ( M_FLUSH = 0x86 NAME_MAX = 0xff NEWDEV = 0x1 + NFDBITS = 0x40 NL0 = 0x0 NL1 = 0x100 NLDLY = 0x100 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go index c4ec7ff87..a7cd331aa 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -1352,8 +1326,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -1691,6 +1666,32 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) sec = int32(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go index 23346dc68..336212e1d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -943,6 +907,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1851,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -2341,6 +2321,42 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc___sysctl_trampoline() + +//go:linkname libc___sysctl libc___sysctl +//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) sec = int32(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s index 37b85b4f6..c6557b135 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -108,6 +104,8 @@ TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 JMP libc_chown(SB) TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 JMP libc_chroot(SB) +TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 JMP libc_close(SB) TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 @@ -264,6 +262,10 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) +TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 + JMP libc___sysctl(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 JMP libc_gettimeofday(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go index 2581e8960..0cba17132 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -1352,8 +1326,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -1691,6 +1666,32 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) sec = int64(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index c142e33e9..b44f628b6 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -1887,8 +1851,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -2356,6 +2321,42 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc___sysctl_trampoline() + +//go:linkname libc___sysctl libc___sysctl +//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) sec = int64(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 1a3915197..ad410cfbc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -266,6 +262,10 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) +TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 + JMP libc___sysctl(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 JMP libc_gettimeofday(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go index f8caecef0..d646e6a11 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -1352,8 +1326,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go index 01cffbf46..163b3912d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -943,6 +907,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1851,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s index 994056f35..66af9f480 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s @@ -64,8 +64,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go index 3fd0f3c85..e8392625c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,16 +361,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -1352,8 +1326,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 8f2691dee..7c5bd510e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -304,27 +304,6 @@ func libc_kevent_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc___sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc___sysctl_trampoline() - -//go:linkname libc___sysctl libc___sysctl -//go:cgo_import_dynamic libc___sysctl __sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -527,21 +506,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) if e1 != 0 { @@ -943,6 +907,21 @@ func libc_chroot_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_clock_gettime_trampoline() + +//go:linkname libc_clock_gettime libc_clock_gettime +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) if e1 != 0 { @@ -1872,8 +1851,9 @@ func libc_lseek_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 61dc0d4c1..96ab9877e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -40,8 +40,6 @@ TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc___sysctl(SB) TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 @@ -64,8 +62,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 @@ -108,6 +104,8 @@ TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 JMP libc_chown(SB) TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 JMP libc_chroot(SB) +TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 JMP libc_close(SB) TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index cdfe9318b..df199b345 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -1272,8 +1272,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index a783306b2..e68185f1e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index f995520d3..2f77f93c4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,8 +361,14 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) } @@ -387,8 +377,8 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -424,6 +414,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index d681acd43..e9a12c9d9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,8 +361,14 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) } @@ -387,8 +377,8 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -424,6 +414,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go index 5049b2ede..27ab0fbda 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { @@ -404,8 +404,8 @@ func Getcwd(buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -414,8 +414,8 @@ func ptrace(request int, pid int, addr uintptr, data int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1606,8 +1606,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index c5e46e4cf..fe5d462e4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index da8819e48..536abcea3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 6ad9be6dd..37823cd6b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index f88331782..794f61264 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 8eebc6c77..1b34b550c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index ecf62a677..5714e2592 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 1ba0f7b6f..88a6b3362 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 20012b2f0..c09dbe345 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index 2b520deaa..42f6c2103 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index d9f044c95..de2cd8db9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 9feed65eb..d51bf07fc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 0a6515088..1e3a3cb73 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index e27f66930..3c97008cd 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -305,6 +305,36 @@ func keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(keyType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(restriction) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func keyctlRestrictKeyring(cmd int, arg2 int) (err error) { + _, _, e1 := Syscall(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 7e0582664..5ade42cce 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index d94d076aa..3e0bbc5f1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index cf5bf3d05..cb0af13a3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index 243a9317c..6fd48d3dc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe() (fd1 int, fd2 int, err error) { r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) fd1 = int(r0) @@ -1498,8 +1498,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index a9532d078..2938e4124 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 0cb9f0177..22b79ab0e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 6fc99b549..cb921f37a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index 27878a72b..5a7438035 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(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 = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -377,6 +361,22 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(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 = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func pipe(p *[2]_C_int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { @@ -1304,8 +1304,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 5f614760c..a96165d4b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -1478,8 +1478,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { - _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) if e1 != 0 { err = e1 } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index e869c0603..7aae554f2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -429,4 +429,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 4917b8ab6..7968439a9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -351,4 +351,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index f85fcb4f8..3c663c69d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 678a119bc..753def987 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -296,4 +296,5 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 222c9f9a2..ac86bd544 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -414,4 +414,5 @@ const ( SYS_FSCONFIG = 4431 SYS_FSMOUNT = 4432 SYS_FSPICK = 4433 + SYS_PIDFD_OPEN = 4434 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 28e6d0e9d..1f5705b58 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -344,4 +344,5 @@ const ( SYS_FSCONFIG = 5431 SYS_FSMOUNT = 5432 SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index e643c6f63..d9ed95326 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -344,4 +344,5 @@ const ( SYS_FSCONFIG = 5431 SYS_FSMOUNT = 5432 SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 01d93c420..94266b65a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -414,4 +414,5 @@ const ( SYS_FSCONFIG = 4431 SYS_FSMOUNT = 4432 SYS_FSPICK = 4433 + SYS_PIDFD_OPEN = 4434 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 5744149eb..52e3da649 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 21c832042..6141f90a8 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -393,4 +393,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index c1bb6d8f2..4f7261a88 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -295,4 +295,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index bc3cc6b5b..f47014ac0 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -358,4 +358,6 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 0a2841ba8..dd78abb0d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -373,4 +373,5 @@ const ( SYS_FSCONFIG = 431 SYS_FSMOUNT = 432 SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 50bc4128f..d02a18350 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -425,6 +432,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -614,6 +622,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -664,6 +673,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2521,3 +2537,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 055eaa76a..f347457e9 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -426,6 +433,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -615,6 +623,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -665,6 +674,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2535,3 +2551,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 66019c9cf..d53d575b8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -289,6 +289,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -429,6 +436,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -618,6 +626,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -668,6 +677,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2512,3 +2528,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 3104798c4..aa41189bd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -616,6 +624,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +675,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2514,3 +2530,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 46c86021b..913efd616 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -288,6 +288,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -617,6 +625,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +676,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2518,3 +2534,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index c2fe1a62a..860fb5dae 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -616,6 +624,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +675,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2516,3 +2532,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index f1eb0d397..12138089a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -616,6 +624,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +675,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2516,3 +2532,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 8759bc36b..2498796fd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -288,6 +288,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 @@ -617,6 +625,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +676,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2518,3 +2534,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index a81200541..17b83f758 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -287,6 +287,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -617,6 +625,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +676,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2524,3 +2540,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 74b7a9199..d289725b6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -287,6 +287,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -428,6 +435,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -617,6 +625,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -667,6 +676,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2524,3 +2540,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 8344583e7..7546c1340 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -286,6 +286,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -427,6 +434,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -616,6 +624,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -666,6 +675,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -808,6 +824,7 @@ type Ustat_t struct { type EpollEvent struct { Events uint32 + _ int32 Fd int32 Pad int32 } @@ -2541,3 +2558,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index d8fc0bc1c..8907bc74b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -285,6 +285,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -426,6 +433,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -615,6 +623,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -665,6 +674,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2538,3 +2554,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 5e0ab9329..5efa151eb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -289,6 +289,13 @@ type RawSockaddrXDP struct { type RawSockaddrPPPoX [0x1e]byte +type RawSockaddrTIPC struct { + Family uint16 + Addrtype uint8 + Scope int8 + Addr [12]byte +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -430,6 +437,7 @@ const ( SizeofSockaddrVM = 0x10 SizeofSockaddrXDP = 0x10 SizeofSockaddrPPPoX = 0x1e + SizeofSockaddrTIPC = 0x10 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 @@ -619,6 +627,7 @@ const ( SizeofRtAttr = 0x4 SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 SizeofRtMsg = 0xc SizeofRtNexthop = 0x8 SizeofNdUseroptmsg = 0x10 @@ -669,6 +678,13 @@ type IfAddrmsg struct { Index uint32 } +type IfaCacheinfo struct { + Prefered uint32 + Valid uint32 + Cstamp uint32 + Tstamp uint32 +} + type RtMsg struct { Family uint8 Dst_len uint8 @@ -2519,3 +2535,58 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } + +type TIPCSocketAddr struct { + Ref uint32 + Node uint32 +} + +type TIPCServiceRange struct { + Type uint32 + Lower uint32 + Upper uint32 +} + +type TIPCServiceName struct { + Type uint32 + Instance uint32 + Domain uint32 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCEvent struct { + Event uint32 + Lower uint32 + Upper uint32 + Port TIPCSocketAddr + S TIPCSubscr +} + +type TIPCGroupReq struct { + Type uint32 + Instance uint32 + Scope uint32 + Flags uint32 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +const ( + TIPC_CLUSTER_SCOPE = 0x2 + TIPC_NODE_SCOPE = 0x3 +) diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index 61b49647b..c605ee6ab 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -9,14 +9,6 @@ import ( "unsafe" ) -const ( - STANDARD_RIGHTS_REQUIRED = 0xf0000 - STANDARD_RIGHTS_READ = 0x20000 - STANDARD_RIGHTS_WRITE = 0x20000 - STANDARD_RIGHTS_EXECUTE = 0x20000 - STANDARD_RIGHTS_ALL = 0x1F0000 -) - const ( NameUnknown = 0 NameFullyQualifiedDN = 1 @@ -235,16 +227,15 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32, } } -// String converts SID to a string format -// suitable for display, storage, or transmission. -func (sid *SID) String() (string, error) { +// String converts SID to a string format suitable for display, storage, or transmission. +func (sid *SID) String() string { var s *uint16 e := ConvertSidToStringSid(sid, &s) if e != nil { - return "", e + return "" } defer LocalFree((Handle)(unsafe.Pointer(s))) - return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil + return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(s))[:]) } // Len returns the length, in bytes, of a valid security identifier SID. @@ -644,6 +635,8 @@ func (tml *Tokenmandatorylabel) Size() uint32 { //sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW //sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW +//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW +//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW // An access token contains the security information for a logon session. // The system creates an access token when a user logs on, and every @@ -654,21 +647,16 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // system-related operations on the local computer. type Token Handle -// OpenCurrentProcessToken opens the access token -// associated with current process. It is a real -// token that needs to be closed, unlike -// GetCurrentProcessToken. +// OpenCurrentProcessToken opens an access token associated with current +// process with TOKEN_QUERY access. It is a real token that needs to be closed. +// +// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...) +// with the desired access instead, or use GetCurrentProcessToken for a +// TOKEN_QUERY token. func OpenCurrentProcessToken() (Token, error) { - p, e := GetCurrentProcess() - if e != nil { - return 0, e - } - var t Token - e = OpenProcessToken(p, TOKEN_QUERY, &t) - if e != nil { - return 0, e - } - return t, nil + var token Token + err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token) + return token, err } // GetCurrentProcessToken returns the access token associated with @@ -785,8 +773,8 @@ func (token Token) GetLinkedToken() (Token, error) { return linkedToken, nil } -// GetSystemDirectory retrieves path to current location of the system -// directory, which is typically, though not always, C:\Windows\System32. +// GetSystemDirectory retrieves the path to current location of the system +// directory, which is typically, though not always, `C:\Windows\System32`. func GetSystemDirectory() (string, error) { n := uint32(MAX_PATH) for { @@ -802,6 +790,42 @@ func GetSystemDirectory() (string, error) { } } +// GetWindowsDirectory retrieves the path to current location of the Windows +// directory, which is typically, though not always, `C:\Windows`. This may +// be a private user directory in the case that the application is running +// under a terminal server. +func GetWindowsDirectory() (string, error) { + n := uint32(MAX_PATH) + for { + b := make([]uint16, n) + l, e := getWindowsDirectory(&b[0], n) + if e != nil { + return "", e + } + if l <= n { + return UTF16ToString(b[:l]), nil + } + n = l + } +} + +// GetSystemWindowsDirectory retrieves the path to current location of the +// Windows directory, which is typically, though not always, `C:\Windows`. +func GetSystemWindowsDirectory() (string, error) { + n := uint32(MAX_PATH) + for { + b := make([]uint16, n) + l, e := getSystemWindowsDirectory(&b[0], n) + if e != nil { + return "", e + } + if l <= n { + return UTF16ToString(b[:l]), nil + } + n = l + } +} + // IsMember reports whether the access token t is a member of the provided SID. func (t Token) IsMember(sid *SID) (bool, error) { var b int32 @@ -852,3 +876,521 @@ type WTS_SESSION_INFO struct { //sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken //sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW //sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory + +type ACL struct { + aclRevision byte + sbz1 byte + aclSize uint16 + aceCount uint16 + sbz2 uint16 +} + +type SECURITY_DESCRIPTOR struct { + revision byte + sbz1 byte + control SECURITY_DESCRIPTOR_CONTROL + owner *SID + group *SID + sacl *ACL + dacl *ACL +} + +type SecurityAttributes struct { + Length uint32 + SecurityDescriptor *SECURITY_DESCRIPTOR + InheritHandle uint32 +} + +type SE_OBJECT_TYPE uint32 + +// Constants for type SE_OBJECT_TYPE +const ( + SE_UNKNOWN_OBJECT_TYPE = 0 + SE_FILE_OBJECT = 1 + SE_SERVICE = 2 + SE_PRINTER = 3 + SE_REGISTRY_KEY = 4 + SE_LMSHARE = 5 + SE_KERNEL_OBJECT = 6 + SE_WINDOW_OBJECT = 7 + SE_DS_OBJECT = 8 + SE_DS_OBJECT_ALL = 9 + SE_PROVIDER_DEFINED_OBJECT = 10 + SE_WMIGUID_OBJECT = 11 + SE_REGISTRY_WOW64_32KEY = 12 + SE_REGISTRY_WOW64_64KEY = 13 +) + +type SECURITY_INFORMATION uint32 + +// Constants for type SECURITY_INFORMATION +const ( + OWNER_SECURITY_INFORMATION = 0x00000001 + GROUP_SECURITY_INFORMATION = 0x00000002 + DACL_SECURITY_INFORMATION = 0x00000004 + SACL_SECURITY_INFORMATION = 0x00000008 + LABEL_SECURITY_INFORMATION = 0x00000010 + ATTRIBUTE_SECURITY_INFORMATION = 0x00000020 + SCOPE_SECURITY_INFORMATION = 0x00000040 + BACKUP_SECURITY_INFORMATION = 0x00010000 + PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 + PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 + UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 + UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 +) + +type SECURITY_DESCRIPTOR_CONTROL uint16 + +// Constants for type SECURITY_DESCRIPTOR_CONTROL +const ( + SE_OWNER_DEFAULTED = 0x0001 + SE_GROUP_DEFAULTED = 0x0002 + SE_DACL_PRESENT = 0x0004 + SE_DACL_DEFAULTED = 0x0008 + SE_SACL_PRESENT = 0x0010 + SE_SACL_DEFAULTED = 0x0020 + SE_DACL_AUTO_INHERIT_REQ = 0x0100 + SE_SACL_AUTO_INHERIT_REQ = 0x0200 + SE_DACL_AUTO_INHERITED = 0x0400 + SE_SACL_AUTO_INHERITED = 0x0800 + SE_DACL_PROTECTED = 0x1000 + SE_SACL_PROTECTED = 0x2000 + SE_RM_CONTROL_VALID = 0x4000 + SE_SELF_RELATIVE = 0x8000 +) + +type ACCESS_MASK uint32 + +// Constants for type ACCESS_MASK +const ( + DELETE = 0x00010000 + READ_CONTROL = 0x00020000 + WRITE_DAC = 0x00040000 + WRITE_OWNER = 0x00080000 + SYNCHRONIZE = 0x00100000 + STANDARD_RIGHTS_REQUIRED = 0x000F0000 + STANDARD_RIGHTS_READ = READ_CONTROL + STANDARD_RIGHTS_WRITE = READ_CONTROL + STANDARD_RIGHTS_EXECUTE = READ_CONTROL + STANDARD_RIGHTS_ALL = 0x001F0000 + SPECIFIC_RIGHTS_ALL = 0x0000FFFF + ACCESS_SYSTEM_SECURITY = 0x01000000 + MAXIMUM_ALLOWED = 0x02000000 + GENERIC_READ = 0x80000000 + GENERIC_WRITE = 0x40000000 + GENERIC_EXECUTE = 0x20000000 + GENERIC_ALL = 0x10000000 +) + +type ACCESS_MODE uint32 + +// Constants for type ACCESS_MODE +const ( + NOT_USED_ACCESS = 0 + GRANT_ACCESS = 1 + SET_ACCESS = 2 + DENY_ACCESS = 3 + REVOKE_ACCESS = 4 + SET_AUDIT_SUCCESS = 5 + SET_AUDIT_FAILURE = 6 +) + +// Constants for AceFlags and Inheritance fields +const ( + NO_INHERITANCE = 0x0 + SUB_OBJECTS_ONLY_INHERIT = 0x1 + SUB_CONTAINERS_ONLY_INHERIT = 0x2 + SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3 + INHERIT_NO_PROPAGATE = 0x4 + INHERIT_ONLY = 0x8 + INHERITED_ACCESS_ENTRY = 0x10 + INHERITED_PARENT = 0x10000000 + INHERITED_GRANDPARENT = 0x20000000 + OBJECT_INHERIT_ACE = 0x1 + CONTAINER_INHERIT_ACE = 0x2 + NO_PROPAGATE_INHERIT_ACE = 0x4 + INHERIT_ONLY_ACE = 0x8 + INHERITED_ACE = 0x10 + VALID_INHERIT_FLAGS = 0x1F +) + +type MULTIPLE_TRUSTEE_OPERATION uint32 + +// Constants for MULTIPLE_TRUSTEE_OPERATION +const ( + NO_MULTIPLE_TRUSTEE = 0 + TRUSTEE_IS_IMPERSONATE = 1 +) + +type TRUSTEE_FORM uint32 + +// Constants for TRUSTEE_FORM +const ( + TRUSTEE_IS_SID = 0 + TRUSTEE_IS_NAME = 1 + TRUSTEE_BAD_FORM = 2 + TRUSTEE_IS_OBJECTS_AND_SID = 3 + TRUSTEE_IS_OBJECTS_AND_NAME = 4 +) + +type TRUSTEE_TYPE uint32 + +// Constants for TRUSTEE_TYPE +const ( + TRUSTEE_IS_UNKNOWN = 0 + TRUSTEE_IS_USER = 1 + TRUSTEE_IS_GROUP = 2 + TRUSTEE_IS_DOMAIN = 3 + TRUSTEE_IS_ALIAS = 4 + TRUSTEE_IS_WELL_KNOWN_GROUP = 5 + TRUSTEE_IS_DELETED = 6 + TRUSTEE_IS_INVALID = 7 + TRUSTEE_IS_COMPUTER = 8 +) + +// Constants for ObjectsPresent field +const ( + ACE_OBJECT_TYPE_PRESENT = 0x1 + ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2 +) + +type EXPLICIT_ACCESS struct { + AccessPermissions ACCESS_MASK + AccessMode ACCESS_MODE + Inheritance uint32 + Trustee TRUSTEE +} + +// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. +type TrusteeValue uintptr + +func TrusteeValueFromString(str string) TrusteeValue { + return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str))) +} +func TrusteeValueFromSID(sid *SID) TrusteeValue { + return TrusteeValue(unsafe.Pointer(sid)) +} +func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue { + return TrusteeValue(unsafe.Pointer(objectsAndSid)) +} +func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue { + return TrusteeValue(unsafe.Pointer(objectsAndName)) +} + +type TRUSTEE struct { + MultipleTrustee *TRUSTEE + MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION + TrusteeForm TRUSTEE_FORM + TrusteeType TRUSTEE_TYPE + TrusteeValue TrusteeValue +} + +type OBJECTS_AND_SID struct { + ObjectsPresent uint32 + ObjectTypeGuid GUID + InheritedObjectTypeGuid GUID + Sid *SID +} + +type OBJECTS_AND_NAME struct { + ObjectsPresent uint32 + ObjectType SE_OBJECT_TYPE + ObjectTypeName *uint16 + InheritedObjectTypeName *uint16 + Name *uint16 +} + +//sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo +//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo +//sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW +//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW + +//sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW +//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor + +//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl +//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl +//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl +//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner +//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup +//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength +//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl +//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor + +//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl +//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl +//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl +//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner +//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup +//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl + +//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW +//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW + +//sys makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD +//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD + +//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW + +// Control returns the security descriptor control bits. +func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { + err = getSecurityDescriptorControl(sd, &control, &revision) + return +} + +// SetControl sets the security descriptor control bits. +func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error { + return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet) +} + +// RMControl returns the security descriptor resource manager control bits. +func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) { + err = getSecurityDescriptorRMControl(sd, &control) + return +} + +// SetRMControl sets the security descriptor resource manager control bits. +func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) { + setSecurityDescriptorRMControl(sd, &rmControl) +} + +// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil +// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns +// ERROR_OBJECT_NOT_FOUND. +func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) { + var present bool + err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted) + if !present { + err = ERROR_OBJECT_NOT_FOUND + } + return +} + +// SetDACL sets the absolute security descriptor DACL. +func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error { + return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted) +} + +// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil +// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns +// ERROR_OBJECT_NOT_FOUND. +func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) { + var present bool + err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted) + if !present { + err = ERROR_OBJECT_NOT_FOUND + } + return +} + +// SetSACL sets the absolute security descriptor SACL. +func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error { + return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted) +} + +// Owner returns the security descriptor owner and whether it was defaulted. +func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) { + err = getSecurityDescriptorOwner(sd, &owner, &defaulted) + return +} + +// SetOwner sets the absolute security descriptor owner. +func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error { + return setSecurityDescriptorOwner(absoluteSD, owner, defaulted) +} + +// Group returns the security descriptor group and whether it was defaulted. +func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) { + err = getSecurityDescriptorGroup(sd, &group, &defaulted) + return +} + +// SetGroup sets the absolute security descriptor owner. +func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error { + return setSecurityDescriptorGroup(absoluteSD, group, defaulted) +} + +// Length returns the length of the security descriptor. +func (sd *SECURITY_DESCRIPTOR) Length() uint32 { + return getSecurityDescriptorLength(sd) +} + +// IsValid returns whether the security descriptor is valid. +func (sd *SECURITY_DESCRIPTOR) IsValid() bool { + return isValidSecurityDescriptor(sd) +} + +// String returns the SDDL form of the security descriptor, with a function signature that can be +// used with %v formatting directives. +func (sd *SECURITY_DESCRIPTOR) String() string { + var sddl *uint16 + err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil) + if err != nil { + return "" + } + defer LocalFree(Handle(unsafe.Pointer(sddl))) + return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:]) +} + +// ToAbsolute converts a self-relative security descriptor into an absolute one. +func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) { + control, _, err := selfRelativeSD.Control() + if err != nil { + return + } + if control&SE_SELF_RELATIVE == 0 { + err = ERROR_INVALID_PARAMETER + return + } + var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32 + err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize, + nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize) + switch err { + case ERROR_INSUFFICIENT_BUFFER: + case nil: + // makeAbsoluteSD is expected to fail, but it succeeds. + return nil, ERROR_INTERNAL_ERROR + default: + return nil, err + } + if absoluteSDSize > 0 { + absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0])) + } + var ( + dacl *ACL + sacl *ACL + owner *SID + group *SID + ) + if daclSize > 0 { + dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0])) + } + if saclSize > 0 { + sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0])) + } + if ownerSize > 0 { + owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0])) + } + if groupSize > 0 { + group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0])) + } + err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize, + dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize) + return +} + +// ToSelfRelative converts an absolute security descriptor into a self-relative one. +func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) { + control, _, err := absoluteSD.Control() + if err != nil { + return + } + if control&SE_SELF_RELATIVE != 0 { + err = ERROR_INVALID_PARAMETER + return + } + var selfRelativeSDSize uint32 + err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize) + switch err { + case ERROR_INSUFFICIENT_BUFFER: + case nil: + // makeSelfRelativeSD is expected to fail, but it succeeds. + return nil, ERROR_INTERNAL_ERROR + default: + return nil, err + } + if selfRelativeSDSize > 0 { + selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0])) + } + err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize) + return +} + +func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR { + sdBytes := make([]byte, selfRelativeSD.Length()) + copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)]) + return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0])) +} + +// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a +// self-relative security descriptor object allocated on the Go heap. +func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// GetSecurityInfo queries the security information for a given handle and returns the self-relative security +// descriptor result on the Go heap. +func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security +// descriptor result on the Go heap. +func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and +// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor +// result on the Go heap. +func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) { + var winHeapSD *SECURITY_DESCRIPTOR + var winHeapSDSize uint32 + var firstAccessEntry *EXPLICIT_ACCESS + if len(accessEntries) > 0 { + firstAccessEntry = &accessEntries[0] + } + var firstAuditEntry *EXPLICIT_ACCESS + if len(auditEntries) > 0 { + firstAuditEntry = &auditEntries[0] + } + err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) + return winHeapSD.copySelfRelativeSecurityDescriptor(), nil +} + +// NewSecurityDescriptor creates and initializes a new absolute security descriptor. +func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) { + absoluteSD = &SECURITY_DESCRIPTOR{} + err = initializeSecurityDescriptor(absoluteSD, 1) + return +} + +// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL. +// Both explicitEntries and mergedACL are optional and can be nil. +func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) { + var firstExplicitEntry *EXPLICIT_ACCESS + if len(explicitEntries) > 0 { + firstExplicitEntry = &explicitEntries[0] + } + var winHeapACL *ACL + err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL) + if err != nil { + return + } + defer LocalFree(Handle(unsafe.Pointer(winHeapACL))) + aclBytes := make([]byte, winHeapACL.aclSize) + copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)]) + return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil +} diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index 03383f1df..847e00bc9 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -159,6 +159,10 @@ type SERVICE_DESCRIPTION struct { Description *uint16 } +type SERVICE_DELAYED_AUTO_START_INFO struct { + IsDelayedAutoStartUp uint32 +} + type SERVICE_STATUS_PROCESS struct { ServiceType uint32 CurrentState uint32 diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index b23050924..4ce8eaf17 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -178,8 +178,6 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys TerminateProcess(handle Handle, exitcode uint32) (err error) //sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) //sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW -//sys GetCurrentProcess() (pseudoHandle Handle, err error) -//sys GetCurrentThread() (pseudoHandle Handle, err error) //sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) //sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) //sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] @@ -257,6 +255,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetEvent(event Handle) (err error) = kernel32.SetEvent //sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent //sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent +//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) = kernel32.CreateMutexW +//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateMutexExW +//sys OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenMutexW +//sys ReleaseMutex(mutex Handle) (err error) = kernel32.ReleaseMutex //sys SleepEx(milliseconds uint32, alertable bool) (ret uint32) = kernel32.SleepEx //sys CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) = kernel32.CreateJobObjectW //sys AssignProcessToJobObject(job Handle, process Handle) (err error) = kernel32.AssignProcessToJobObject @@ -269,6 +271,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) //sys GetProcessId(process Handle) (id uint32, err error) //sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) +//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost // Volume Management Functions //sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW @@ -291,14 +294,47 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW //sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW //sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW +//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx +//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW +//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters +//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters //sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString //sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2 //sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid //sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree //sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion +//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers // syscall interface implementation for other packages +// GetCurrentProcess returns the handle for the current process. +// It is a pseudo handle that does not need to be closed. +// The returned error is always nil. +// +// Deprecated: use CurrentProcess for the same Handle without the nil +// error. +func GetCurrentProcess() (Handle, error) { + return CurrentProcess(), nil +} + +// CurrentProcess returns the handle for the current process. +// It is a pseudo handle that does not need to be closed. +func CurrentProcess() Handle { return Handle(^uintptr(1 - 1)) } + +// GetCurrentThread returns the handle for the current thread. +// It is a pseudo handle that does not need to be closed. +// The returned error is always nil. +// +// Deprecated: use CurrentThread for the same Handle without the nil +// error. +func GetCurrentThread() (Handle, error) { + return CurrentThread(), nil +} + +// CurrentThread returns the handle for the current thread. +// It is a pseudo handle that does not need to be closed. +func CurrentThread() Handle { return Handle(^uintptr(2 - 1)) } + // GetProcAddressByOrdinal retrieves the address of the exported // function from module by ordinal. func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) { @@ -1306,8 +1342,8 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil } -// RtlGetVersion returns the true version of the underlying operating system, ignoring -// any manifesting or compatibility layers on top of the win32 layer. +// RtlGetVersion returns the version of the underlying operating system, ignoring +// manifest semantics but is affected by the application compatibility layer. func RtlGetVersion() *OsVersionInfoEx { info := &OsVersionInfoEx{} info.osVersionInfoSize = uint32(unsafe.Sizeof(*info)) @@ -1318,3 +1354,11 @@ func RtlGetVersion() *OsVersionInfoEx { _ = rtlGetVersion(info) return info } + +// RtlGetNtVersionNumbers returns the version of the underlying operating system, +// ignoring manifest semantics and the application compatibility layer. +func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) { + rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber) + buildNumber &= 0xffff + return +} diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 1e3947f0f..a54823414 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -62,11 +62,6 @@ var signals = [...]string{ } const ( - GENERIC_READ = 0x80000000 - GENERIC_WRITE = 0x40000000 - GENERIC_EXECUTE = 0x20000000 - GENERIC_ALL = 0x10000000 - FILE_LIST_DIRECTORY = 0x00000001 FILE_APPEND_DATA = 0x00000004 FILE_WRITE_ATTRIBUTES = 0x00000100 @@ -158,13 +153,6 @@ const ( WAIT_OBJECT_0 = 0x00000000 WAIT_FAILED = 0xFFFFFFFF - // Standard access rights. - DELETE = 0x00010000 - READ_CONTROL = 0x00020000 - SYNCHRONIZE = 0x00100000 - WRITE_DAC = 0x00040000 - WRITE_OWNER = 0x00080000 - // Access rights for process. PROCESS_CREATE_PROCESS = 0x0080 PROCESS_CREATE_THREAD = 0x0002 @@ -483,12 +471,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) { return } -type SecurityAttributes struct { - Length uint32 - SecurityDescriptor uintptr - InheritHandle uint32 -} - type Overlapped struct { Internal uintptr InternalHigh uintptr @@ -1190,6 +1172,28 @@ const ( REG_QWORD = REG_QWORD_LITTLE_ENDIAN ) +const ( + EVENT_MODIFY_STATE = 0x0002 + EVENT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3 + + MUTANT_QUERY_STATE = 0x0001 + MUTANT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | MUTANT_QUERY_STATE + + SEMAPHORE_MODIFY_STATE = 0x0002 + SEMAPHORE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3 + + TIMER_QUERY_STATE = 0x0001 + TIMER_MODIFY_STATE = 0x0002 + TIMER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | TIMER_QUERY_STATE | TIMER_MODIFY_STATE + + MUTEX_MODIFY_STATE = MUTANT_QUERY_STATE + MUTEX_ALL_ACCESS = MUTANT_ALL_ACCESS + + CREATE_EVENT_MANUAL_RESET = 0x1 + CREATE_EVENT_INITIAL_SET = 0x2 + CREATE_MUTEX_INITIAL_OWNER = 0x1 +) + type AddrinfoW struct { Flags int32 Family int32 @@ -1666,3 +1670,68 @@ type OsVersionInfoEx struct { ProductType byte _ byte } + +const ( + EWX_LOGOFF = 0x00000000 + EWX_SHUTDOWN = 0x00000001 + EWX_REBOOT = 0x00000002 + EWX_FORCE = 0x00000004 + EWX_POWEROFF = 0x00000008 + EWX_FORCEIFHUNG = 0x00000010 + EWX_QUICKRESOLVE = 0x00000020 + EWX_RESTARTAPPS = 0x00000040 + EWX_HYBRID_SHUTDOWN = 0x00400000 + EWX_BOOTOPTIONS = 0x01000000 + + SHTDN_REASON_FLAG_COMMENT_REQUIRED = 0x01000000 + SHTDN_REASON_FLAG_DIRTY_PROBLEM_ID_REQUIRED = 0x02000000 + SHTDN_REASON_FLAG_CLEAN_UI = 0x04000000 + SHTDN_REASON_FLAG_DIRTY_UI = 0x08000000 + SHTDN_REASON_FLAG_USER_DEFINED = 0x40000000 + SHTDN_REASON_FLAG_PLANNED = 0x80000000 + SHTDN_REASON_MAJOR_OTHER = 0x00000000 + SHTDN_REASON_MAJOR_NONE = 0x00000000 + SHTDN_REASON_MAJOR_HARDWARE = 0x00010000 + SHTDN_REASON_MAJOR_OPERATINGSYSTEM = 0x00020000 + SHTDN_REASON_MAJOR_SOFTWARE = 0x00030000 + SHTDN_REASON_MAJOR_APPLICATION = 0x00040000 + SHTDN_REASON_MAJOR_SYSTEM = 0x00050000 + SHTDN_REASON_MAJOR_POWER = 0x00060000 + SHTDN_REASON_MAJOR_LEGACY_API = 0x00070000 + SHTDN_REASON_MINOR_OTHER = 0x00000000 + SHTDN_REASON_MINOR_NONE = 0x000000ff + SHTDN_REASON_MINOR_MAINTENANCE = 0x00000001 + SHTDN_REASON_MINOR_INSTALLATION = 0x00000002 + SHTDN_REASON_MINOR_UPGRADE = 0x00000003 + SHTDN_REASON_MINOR_RECONFIG = 0x00000004 + SHTDN_REASON_MINOR_HUNG = 0x00000005 + SHTDN_REASON_MINOR_UNSTABLE = 0x00000006 + SHTDN_REASON_MINOR_DISK = 0x00000007 + SHTDN_REASON_MINOR_PROCESSOR = 0x00000008 + SHTDN_REASON_MINOR_NETWORKCARD = 0x00000009 + SHTDN_REASON_MINOR_POWER_SUPPLY = 0x0000000a + SHTDN_REASON_MINOR_CORDUNPLUGGED = 0x0000000b + SHTDN_REASON_MINOR_ENVIRONMENT = 0x0000000c + SHTDN_REASON_MINOR_HARDWARE_DRIVER = 0x0000000d + SHTDN_REASON_MINOR_OTHERDRIVER = 0x0000000e + SHTDN_REASON_MINOR_BLUESCREEN = 0x0000000F + SHTDN_REASON_MINOR_SERVICEPACK = 0x00000010 + SHTDN_REASON_MINOR_HOTFIX = 0x00000011 + SHTDN_REASON_MINOR_SECURITYFIX = 0x00000012 + SHTDN_REASON_MINOR_SECURITY = 0x00000013 + SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY = 0x00000014 + SHTDN_REASON_MINOR_WMI = 0x00000015 + SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL = 0x00000016 + SHTDN_REASON_MINOR_HOTFIX_UNINSTALL = 0x00000017 + SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL = 0x00000018 + SHTDN_REASON_MINOR_MMC = 0x00000019 + SHTDN_REASON_MINOR_SYSTEMRESTORE = 0x0000001a + SHTDN_REASON_MINOR_TERMSRV = 0x00000020 + SHTDN_REASON_MINOR_DC_PROMOTION = 0x00000021 + SHTDN_REASON_MINOR_DC_DEMOTION = 0x00000022 + SHTDN_REASON_UNKNOWN = SHTDN_REASON_MINOR_NONE + SHTDN_REASON_LEGACY_API = SHTDN_REASON_MAJOR_LEGACY_API | SHTDN_REASON_FLAG_PLANNED + SHTDN_REASON_VALID_BIT_MASK = 0xc0ffffff + + SHUTDOWN_NORETRY = 0x1 +) diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index d461bed98..8008c0307 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -51,261 +51,296 @@ var ( modnetapi32 = NewLazySystemDLL("netapi32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") - procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") - procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") - procReportEventW = modadvapi32.NewProc("ReportEventW") - procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") - procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") - procCreateServiceW = modadvapi32.NewProc("CreateServiceW") - procOpenServiceW = modadvapi32.NewProc("OpenServiceW") - procDeleteService = modadvapi32.NewProc("DeleteService") - procStartServiceW = modadvapi32.NewProc("StartServiceW") - procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") - procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") - procControlService = modadvapi32.NewProc("ControlService") - procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") - procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") - procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") - procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") - procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") - procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") - procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") - procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") - procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") - procGetLastError = modkernel32.NewProc("GetLastError") - procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") - procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") - procFreeLibrary = modkernel32.NewProc("FreeLibrary") - procGetProcAddress = modkernel32.NewProc("GetProcAddress") - procGetVersion = modkernel32.NewProc("GetVersion") - procFormatMessageW = modkernel32.NewProc("FormatMessageW") - procExitProcess = modkernel32.NewProc("ExitProcess") - procIsWow64Process = modkernel32.NewProc("IsWow64Process") - procCreateFileW = modkernel32.NewProc("CreateFileW") - procReadFile = modkernel32.NewProc("ReadFile") - procWriteFile = modkernel32.NewProc("WriteFile") - procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") - procSetFilePointer = modkernel32.NewProc("SetFilePointer") - procCloseHandle = modkernel32.NewProc("CloseHandle") - procGetStdHandle = modkernel32.NewProc("GetStdHandle") - procSetStdHandle = modkernel32.NewProc("SetStdHandle") - procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") - procFindNextFileW = modkernel32.NewProc("FindNextFileW") - procFindClose = modkernel32.NewProc("FindClose") - procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") - procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") - procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") - procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") - procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") - procDeleteFileW = modkernel32.NewProc("DeleteFileW") - procMoveFileW = modkernel32.NewProc("MoveFileW") - procMoveFileExW = modkernel32.NewProc("MoveFileExW") - procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") - procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") - procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") - procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") - procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") - procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") - procCancelIo = modkernel32.NewProc("CancelIo") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procCreateProcessW = modkernel32.NewProc("CreateProcessW") - procOpenProcess = modkernel32.NewProc("OpenProcess") - procShellExecuteW = modshell32.NewProc("ShellExecuteW") - procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") - procTerminateProcess = modkernel32.NewProc("TerminateProcess") - procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") - procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") - procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") - procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") - procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") - procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") - procGetTempPathW = modkernel32.NewProc("GetTempPathW") - procCreatePipe = modkernel32.NewProc("CreatePipe") - procGetFileType = modkernel32.NewProc("GetFileType") - procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") - procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") - procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") - procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") - procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") - procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") - procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") - procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") - procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") - procGetTickCount64 = modkernel32.NewProc("GetTickCount64") - procSetFileTime = modkernel32.NewProc("SetFileTime") - procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") - procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") - procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") - procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") - procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") - procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") - procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") - procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") - procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") - procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") - procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") - procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") - procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") - procVirtualLock = modkernel32.NewProc("VirtualLock") - procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") - procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") - procVirtualFree = modkernel32.NewProc("VirtualFree") - procVirtualProtect = modkernel32.NewProc("VirtualProtect") - procTransmitFile = modmswsock.NewProc("TransmitFile") - procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") - procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") - procCertOpenStore = modcrypt32.NewProc("CertOpenStore") - procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") - procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") - procCertCloseStore = modcrypt32.NewProc("CertCloseStore") - procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") - procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") - procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") - procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") - procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") - procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") - procRegCloseKey = modadvapi32.NewProc("RegCloseKey") - procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") - procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") - procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") - procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") - procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") - procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") - procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") - procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") - procReadConsoleW = modkernel32.NewProc("ReadConsoleW") - procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") - procProcess32FirstW = modkernel32.NewProc("Process32FirstW") - procProcess32NextW = modkernel32.NewProc("Process32NextW") - procThread32First = modkernel32.NewProc("Thread32First") - procThread32Next = modkernel32.NewProc("Thread32Next") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") - procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") - procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") - procCreateEventW = modkernel32.NewProc("CreateEventW") - procCreateEventExW = modkernel32.NewProc("CreateEventExW") - procOpenEventW = modkernel32.NewProc("OpenEventW") - procSetEvent = modkernel32.NewProc("SetEvent") - procResetEvent = modkernel32.NewProc("ResetEvent") - procPulseEvent = modkernel32.NewProc("PulseEvent") - procSleepEx = modkernel32.NewProc("SleepEx") - procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") - procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") - procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") - procSetErrorMode = modkernel32.NewProc("SetErrorMode") - procResumeThread = modkernel32.NewProc("ResumeThread") - procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") - procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") - procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") - procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") - procGetProcessId = modkernel32.NewProc("GetProcessId") - procOpenThread = modkernel32.NewProc("OpenThread") - procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW") - procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") - procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") - procFindFirstVolumeMountPointW = modkernel32.NewProc("FindFirstVolumeMountPointW") - procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") - procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW") - procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") - procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") - procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") - procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") - procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") - procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") - procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW") - procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW") - procGetVolumePathNameW = modkernel32.NewProc("GetVolumePathNameW") - procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") - procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") - procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") - procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") - procMessageBoxW = moduser32.NewProc("MessageBoxW") - procCLSIDFromString = modole32.NewProc("CLSIDFromString") - procStringFromGUID2 = modole32.NewProc("StringFromGUID2") - procCoCreateGuid = modole32.NewProc("CoCreateGuid") - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") - procRtlGetVersion = modntdll.NewProc("RtlGetVersion") - procWSAStartup = modws2_32.NewProc("WSAStartup") - procWSACleanup = modws2_32.NewProc("WSACleanup") - procWSAIoctl = modws2_32.NewProc("WSAIoctl") - procsocket = modws2_32.NewProc("socket") - procsetsockopt = modws2_32.NewProc("setsockopt") - procgetsockopt = modws2_32.NewProc("getsockopt") - procbind = modws2_32.NewProc("bind") - procconnect = modws2_32.NewProc("connect") - procgetsockname = modws2_32.NewProc("getsockname") - procgetpeername = modws2_32.NewProc("getpeername") - proclisten = modws2_32.NewProc("listen") - procshutdown = modws2_32.NewProc("shutdown") - procclosesocket = modws2_32.NewProc("closesocket") - procAcceptEx = modmswsock.NewProc("AcceptEx") - procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") - procWSARecv = modws2_32.NewProc("WSARecv") - procWSASend = modws2_32.NewProc("WSASend") - procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") - procWSASendTo = modws2_32.NewProc("WSASendTo") - procgethostbyname = modws2_32.NewProc("gethostbyname") - procgetservbyname = modws2_32.NewProc("getservbyname") - procntohs = modws2_32.NewProc("ntohs") - procgetprotobyname = modws2_32.NewProc("getprotobyname") - procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") - procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") - procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") - procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") - procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") - procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") - procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") - procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") - procGetACP = modkernel32.NewProc("GetACP") - procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") - procTranslateNameW = modsecur32.NewProc("TranslateNameW") - procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") - procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") - procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") - procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") - procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") - procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procGetLengthSid = modadvapi32.NewProc("GetLengthSid") - procCopySid = modadvapi32.NewProc("CopySid") - procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") - procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") - procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") - procFreeSid = modadvapi32.NewProc("FreeSid") - procEqualSid = modadvapi32.NewProc("EqualSid") - procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") - procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") - procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") - procIsValidSid = modadvapi32.NewProc("IsValidSid") - procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") - procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procSetThreadToken = modadvapi32.NewProc("SetThreadToken") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") - procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") - procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") - procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") - procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") - procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") - procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") - procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") - procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") + procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") + procReportEventW = modadvapi32.NewProc("ReportEventW") + procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") + procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") + procCreateServiceW = modadvapi32.NewProc("CreateServiceW") + procOpenServiceW = modadvapi32.NewProc("OpenServiceW") + procDeleteService = modadvapi32.NewProc("DeleteService") + procStartServiceW = modadvapi32.NewProc("StartServiceW") + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") + procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") + procControlService = modadvapi32.NewProc("ControlService") + procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") + procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") + procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") + procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") + procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") + procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") + procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") + procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") + procGetLastError = modkernel32.NewProc("GetLastError") + procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") + procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") + procFreeLibrary = modkernel32.NewProc("FreeLibrary") + procGetProcAddress = modkernel32.NewProc("GetProcAddress") + procGetVersion = modkernel32.NewProc("GetVersion") + procFormatMessageW = modkernel32.NewProc("FormatMessageW") + procExitProcess = modkernel32.NewProc("ExitProcess") + procIsWow64Process = modkernel32.NewProc("IsWow64Process") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procReadFile = modkernel32.NewProc("ReadFile") + procWriteFile = modkernel32.NewProc("WriteFile") + procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") + procSetFilePointer = modkernel32.NewProc("SetFilePointer") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procGetStdHandle = modkernel32.NewProc("GetStdHandle") + procSetStdHandle = modkernel32.NewProc("SetStdHandle") + procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") + procFindNextFileW = modkernel32.NewProc("FindNextFileW") + procFindClose = modkernel32.NewProc("FindClose") + procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") + procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") + procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procDeleteFileW = modkernel32.NewProc("DeleteFileW") + procMoveFileW = modkernel32.NewProc("MoveFileW") + procMoveFileExW = modkernel32.NewProc("MoveFileExW") + procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") + procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") + procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") + procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") + procCancelIo = modkernel32.NewProc("CancelIo") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCreateProcessW = modkernel32.NewProc("CreateProcessW") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procShellExecuteW = modshell32.NewProc("ShellExecuteW") + procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") + procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") + procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") + procGetTempPathW = modkernel32.NewProc("GetTempPathW") + procCreatePipe = modkernel32.NewProc("CreatePipe") + procGetFileType = modkernel32.NewProc("GetFileType") + procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") + procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") + procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") + procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") + procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") + procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") + procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") + procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") + procGetTickCount64 = modkernel32.NewProc("GetTickCount64") + procSetFileTime = modkernel32.NewProc("SetFileTime") + procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") + procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") + procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") + procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") + procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") + procLocalFree = modkernel32.NewProc("LocalFree") + procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") + procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") + procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") + procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") + procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") + procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") + procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") + procVirtualLock = modkernel32.NewProc("VirtualLock") + procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") + procVirtualFree = modkernel32.NewProc("VirtualFree") + procVirtualProtect = modkernel32.NewProc("VirtualProtect") + procTransmitFile = modmswsock.NewProc("TransmitFile") + procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") + procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") + procCertOpenStore = modcrypt32.NewProc("CertOpenStore") + procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") + procCertCloseStore = modcrypt32.NewProc("CertCloseStore") + procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") + procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") + procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") + procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") + procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") + procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") + procRegCloseKey = modadvapi32.NewProc("RegCloseKey") + procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") + procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") + procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") + procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") + procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") + procReadConsoleW = modkernel32.NewProc("ReadConsoleW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procThread32First = modkernel32.NewProc("Thread32First") + procThread32Next = modkernel32.NewProc("Thread32Next") + procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") + procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") + procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procCreateEventExW = modkernel32.NewProc("CreateEventExW") + procOpenEventW = modkernel32.NewProc("OpenEventW") + procSetEvent = modkernel32.NewProc("SetEvent") + procResetEvent = modkernel32.NewProc("ResetEvent") + procPulseEvent = modkernel32.NewProc("PulseEvent") + procCreateMutexW = modkernel32.NewProc("CreateMutexW") + procCreateMutexExW = modkernel32.NewProc("CreateMutexExW") + procOpenMutexW = modkernel32.NewProc("OpenMutexW") + procReleaseMutex = modkernel32.NewProc("ReleaseMutex") + procSleepEx = modkernel32.NewProc("SleepEx") + procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") + procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") + procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") + procSetErrorMode = modkernel32.NewProc("SetErrorMode") + procResumeThread = modkernel32.NewProc("ResumeThread") + procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") + procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") + procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") + procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") + procGetProcessId = modkernel32.NewProc("GetProcessId") + procOpenThread = modkernel32.NewProc("OpenThread") + procSetProcessPriorityBoost = modkernel32.NewProc("SetProcessPriorityBoost") + procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW") + procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") + procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") + procFindFirstVolumeMountPointW = modkernel32.NewProc("FindFirstVolumeMountPointW") + procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") + procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW") + procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") + procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") + procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") + procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") + procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") + procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") + procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW") + procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW") + procGetVolumePathNameW = modkernel32.NewProc("GetVolumePathNameW") + procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") + procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") + procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") + procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") + procMessageBoxW = moduser32.NewProc("MessageBoxW") + procExitWindowsEx = moduser32.NewProc("ExitWindowsEx") + procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW") + procSetProcessShutdownParameters = modkernel32.NewProc("SetProcessShutdownParameters") + procGetProcessShutdownParameters = modkernel32.NewProc("GetProcessShutdownParameters") + procCLSIDFromString = modole32.NewProc("CLSIDFromString") + procStringFromGUID2 = modole32.NewProc("StringFromGUID2") + procCoCreateGuid = modole32.NewProc("CoCreateGuid") + procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") + procRtlGetVersion = modntdll.NewProc("RtlGetVersion") + procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") + procWSAStartup = modws2_32.NewProc("WSAStartup") + procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSAIoctl = modws2_32.NewProc("WSAIoctl") + procsocket = modws2_32.NewProc("socket") + procsetsockopt = modws2_32.NewProc("setsockopt") + procgetsockopt = modws2_32.NewProc("getsockopt") + procbind = modws2_32.NewProc("bind") + procconnect = modws2_32.NewProc("connect") + procgetsockname = modws2_32.NewProc("getsockname") + procgetpeername = modws2_32.NewProc("getpeername") + proclisten = modws2_32.NewProc("listen") + procshutdown = modws2_32.NewProc("shutdown") + procclosesocket = modws2_32.NewProc("closesocket") + procAcceptEx = modmswsock.NewProc("AcceptEx") + procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") + procWSARecv = modws2_32.NewProc("WSARecv") + procWSASend = modws2_32.NewProc("WSASend") + procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") + procWSASendTo = modws2_32.NewProc("WSASendTo") + procgethostbyname = modws2_32.NewProc("gethostbyname") + procgetservbyname = modws2_32.NewProc("getservbyname") + procntohs = modws2_32.NewProc("ntohs") + procgetprotobyname = modws2_32.NewProc("getprotobyname") + procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") + procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") + procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") + procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") + procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") + procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procGetACP = modkernel32.NewProc("GetACP") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") + procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") + procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") + procGetLengthSid = modadvapi32.NewProc("GetLengthSid") + procCopySid = modadvapi32.NewProc("CopySid") + procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") + procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") + procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") + procFreeSid = modadvapi32.NewProc("FreeSid") + procEqualSid = modadvapi32.NewProc("EqualSid") + procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") + procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") + procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") + procIsValidSid = modadvapi32.NewProc("IsValidSid") + procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") + procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procSetThreadToken = modadvapi32.NewProc("SetThreadToken") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") + procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") + procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") + procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") + procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") + procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") + procGetSystemWindowsDirectoryW = modkernel32.NewProc("GetSystemWindowsDirectoryW") + procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") + procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") + procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") + procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") + procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo") + procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") + procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW") + procBuildSecurityDescriptorW = modadvapi32.NewProc("BuildSecurityDescriptorW") + procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor") + procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") + procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl") + procGetSecurityDescriptorSacl = modadvapi32.NewProc("GetSecurityDescriptorSacl") + procGetSecurityDescriptorOwner = modadvapi32.NewProc("GetSecurityDescriptorOwner") + procGetSecurityDescriptorGroup = modadvapi32.NewProc("GetSecurityDescriptorGroup") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procGetSecurityDescriptorRMControl = modadvapi32.NewProc("GetSecurityDescriptorRMControl") + procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor") + procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl") + procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") + procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") + procSetSecurityDescriptorOwner = modadvapi32.NewProc("SetSecurityDescriptorOwner") + procSetSecurityDescriptorGroup = modadvapi32.NewProc("SetSecurityDescriptorGroup") + procSetSecurityDescriptorRMControl = modadvapi32.NewProc("SetSecurityDescriptorRMControl") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") + procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") + procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") + procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") ) func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { @@ -682,7 +717,14 @@ func ExitProcess(exitcode uint32) { } func IsWow64Process(handle Handle, isWow64 *bool) (err error) { - r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(isWow64)), 0) + var _p0 uint32 + if *isWow64 { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) + *isWow64 = _p0 != 0 if r1 == 0 { if e1 != 0 { err = errnoErr(e1) @@ -1165,32 +1207,6 @@ func GetStartupInfo(startupInfo *StartupInfo) (err error) { return } -func GetCurrentProcess() (pseudoHandle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0) - pseudoHandle = Handle(r0) - if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetCurrentThread() (pseudoHandle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) - pseudoHandle = Handle(r0) - if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) if r1 == 0 { @@ -2105,6 +2121,69 @@ func PulseEvent(event Handle) (err error) { return } +func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if initialOwner { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReleaseMutex(mutex Handle) (err error) { + r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { var _p0 uint32 if alertable { @@ -2255,6 +2334,24 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand return } +func SetProcessPriorityBoost(process Handle, disable bool) (err error) { + var _p0 uint32 + if disable { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) if r1 == 0 { @@ -2495,6 +2592,66 @@ func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret return } +func ExitWindowsEx(flags uint32, reason uint32) (err error) { + r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) { + var _p0 uint32 + if forceAppsClosed { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if rebootAfterShutdown { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) if r0 != 0 { @@ -2530,6 +2687,11 @@ func rtlGetVersion(info *OsVersionInfoEx) (ret error) { return } +func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { + syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) + return +} + func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) if r0 != 0 { @@ -3307,6 +3469,32 @@ func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { return } +func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func WTSQueryUserToken(session uint32, token *Token) (err error) { r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) if r1 == 0 { @@ -3335,3 +3523,358 @@ func WTSFreeMemory(ptr uintptr) { syscall.Syscall(procWTSFreeMemory.Addr(), 1, uintptr(ptr), 0, 0) return } + +func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { + syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + return +} + +func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _getNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl, sd) +} + +func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _SetNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl) +} + +func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { + r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) { + var _p0 uint32 + if *daclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if *daclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *daclPresent = _p0 != 0 + *daclDefaulted = _p1 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) { + var _p0 uint32 + if *saclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if *saclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *saclPresent = _p0 != 0 + *saclDefaulted = _p1 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) { + var _p0 uint32 + if *ownerDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) + *ownerDefaulted = _p0 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) { + var _p0 uint32 + if *groupDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) + *groupDefaulted = _p0 != 0 + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + len = uint32(r0) + return +} + +func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { + r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + isValid = r0 != 0 + return +} + +func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) { + var _p0 uint32 + if daclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if daclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) { + var _p0 uint32 + if saclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if saclDefaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) { + var _p0 uint32 + if ownerDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) { + var _p0 uint32 + if groupDefaulted { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { + syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { + r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} diff --git a/vendor/golang.org/x/text/encoding/charmap/maketables.go b/vendor/golang.org/x/text/encoding/charmap/maketables.go new file mode 100644 index 000000000..f7941701e --- /dev/null +++ b/vendor/golang.org/x/text/encoding/charmap/maketables.go @@ -0,0 +1,556 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" + "unicode/utf8" + + "golang.org/x/text/encoding" + "golang.org/x/text/internal/gen" +) + +const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + + ` !"#$%&'()*+,-./0123456789:;<=>?` + + `@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` + + "`abcdefghijklmnopqrstuvwxyz{|}~\u007f" + +var encodings = []struct { + name string + mib string + comment string + varName string + replacement byte + mapping string +}{ + { + "IBM Code Page 037", + "IBM037", + "", + "CodePage037", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm", + }, + { + "IBM Code Page 437", + "PC8CodePage437", + "", + "CodePage437", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm", + }, + { + "IBM Code Page 850", + "PC850Multilingual", + "", + "CodePage850", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm", + }, + { + "IBM Code Page 852", + "PCp852", + "", + "CodePage852", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm", + }, + { + "IBM Code Page 855", + "IBM855", + "", + "CodePage855", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm", + }, + { + "Windows Code Page 858", // PC latin1 with Euro + "IBM00858", + "", + "CodePage858", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm", + }, + { + "IBM Code Page 860", + "IBM860", + "", + "CodePage860", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm", + }, + { + "IBM Code Page 862", + "PC862LatinHebrew", + "", + "CodePage862", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm", + }, + { + "IBM Code Page 863", + "IBM863", + "", + "CodePage863", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm", + }, + { + "IBM Code Page 865", + "IBM865", + "", + "CodePage865", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm", + }, + { + "IBM Code Page 866", + "IBM866", + "", + "CodePage866", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-ibm866.txt", + }, + { + "IBM Code Page 1047", + "IBM1047", + "", + "CodePage1047", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm", + }, + { + "IBM Code Page 1140", + "IBM01140", + "", + "CodePage1140", + 0x3f, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm", + }, + { + "ISO 8859-1", + "ISOLatin1", + "", + "ISO8859_1", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm", + }, + { + "ISO 8859-2", + "ISOLatin2", + "", + "ISO8859_2", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-2.txt", + }, + { + "ISO 8859-3", + "ISOLatin3", + "", + "ISO8859_3", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-3.txt", + }, + { + "ISO 8859-4", + "ISOLatin4", + "", + "ISO8859_4", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-4.txt", + }, + { + "ISO 8859-5", + "ISOLatinCyrillic", + "", + "ISO8859_5", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-5.txt", + }, + { + "ISO 8859-6", + "ISOLatinArabic", + "", + "ISO8859_6,ISO8859_6E,ISO8859_6I", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-6.txt", + }, + { + "ISO 8859-7", + "ISOLatinGreek", + "", + "ISO8859_7", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-7.txt", + }, + { + "ISO 8859-8", + "ISOLatinHebrew", + "", + "ISO8859_8,ISO8859_8E,ISO8859_8I", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-8.txt", + }, + { + "ISO 8859-9", + "ISOLatin5", + "", + "ISO8859_9", + encoding.ASCIISub, + "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm", + }, + { + "ISO 8859-10", + "ISOLatin6", + "", + "ISO8859_10", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-10.txt", + }, + { + "ISO 8859-13", + "ISO885913", + "", + "ISO8859_13", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-13.txt", + }, + { + "ISO 8859-14", + "ISO885914", + "", + "ISO8859_14", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-14.txt", + }, + { + "ISO 8859-15", + "ISO885915", + "", + "ISO8859_15", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-15.txt", + }, + { + "ISO 8859-16", + "ISO885916", + "", + "ISO8859_16", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-iso-8859-16.txt", + }, + { + "KOI8-R", + "KOI8R", + "", + "KOI8R", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-koi8-r.txt", + }, + { + "KOI8-U", + "KOI8U", + "", + "KOI8U", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-koi8-u.txt", + }, + { + "Macintosh", + "Macintosh", + "", + "Macintosh", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-macintosh.txt", + }, + { + "Macintosh Cyrillic", + "MacintoshCyrillic", + "", + "MacintoshCyrillic", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt", + }, + { + "Windows 874", + "Windows874", + "", + "Windows874", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-874.txt", + }, + { + "Windows 1250", + "Windows1250", + "", + "Windows1250", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1250.txt", + }, + { + "Windows 1251", + "Windows1251", + "", + "Windows1251", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1251.txt", + }, + { + "Windows 1252", + "Windows1252", + "", + "Windows1252", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1252.txt", + }, + { + "Windows 1253", + "Windows1253", + "", + "Windows1253", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1253.txt", + }, + { + "Windows 1254", + "Windows1254", + "", + "Windows1254", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1254.txt", + }, + { + "Windows 1255", + "Windows1255", + "", + "Windows1255", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1255.txt", + }, + { + "Windows 1256", + "Windows1256", + "", + "Windows1256", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1256.txt", + }, + { + "Windows 1257", + "Windows1257", + "", + "Windows1257", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1257.txt", + }, + { + "Windows 1258", + "Windows1258", + "", + "Windows1258", + encoding.ASCIISub, + "http://encoding.spec.whatwg.org/index-windows-1258.txt", + }, + { + "X-User-Defined", + "XUserDefined", + "It is defined at http://encoding.spec.whatwg.org/#x-user-defined", + "XUserDefined", + encoding.ASCIISub, + ascii + + "\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" + + "\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" + + "\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" + + "\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" + + "\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" + + "\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" + + "\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" + + "\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" + + "\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" + + "\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" + + "\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" + + "\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" + + "\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" + + "\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" + + "\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" + + "\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff", + }, +} + +func getWHATWG(url string) string { + res, err := http.Get(url) + if err != nil { + log.Fatalf("%q: Get: %v", url, err) + } + defer res.Body.Close() + + mapping := make([]rune, 128) + for i := range mapping { + mapping[i] = '\ufffd' + } + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := 0, 0 + if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 128 <= x { + log.Fatalf("code %d is out of range", x) + } + if 0x80 <= y && y < 0xa0 { + // We diverge from the WHATWG spec by mapping control characters + // in the range [0x80, 0xa0) to U+FFFD. + continue + } + mapping[x] = rune(y) + } + return ascii + string(mapping) +} + +func getUCM(url string) string { + res, err := http.Get(url) + if err != nil { + log.Fatalf("%q: Get: %v", url, err) + } + defer res.Body.Close() + + mapping := make([]rune, 256) + for i := range mapping { + mapping[i] = '\ufffd' + } + + charsFound := 0 + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + var c byte + var r rune + if _, err := fmt.Sscanf(s, ` \x%x |0`, &r, &c); err != nil { + continue + } + mapping[c] = r + charsFound++ + } + + if charsFound < 200 { + log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound) + } + + return string(mapping) +} + +func main() { + mibs := map[string]bool{} + all := []string{} + + w := gen.NewCodeWriter() + defer w.WriteGoFile("tables.go", "charmap") + + printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) } + + printf("import (\n") + printf("\t\"golang.org/x/text/encoding\"\n") + printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n") + printf(")\n\n") + for _, e := range encodings { + varNames := strings.Split(e.varName, ",") + all = append(all, varNames...) + varName := varNames[0] + switch { + case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"): + e.mapping = getWHATWG(e.mapping) + case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"): + e.mapping = getUCM(e.mapping) + } + + asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00 + if asciiSuperset { + low = 0x80 + } + lvn := 1 + if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") { + lvn = 3 + } + lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:] + printf("// %s is the %s encoding.\n", varName, e.name) + if e.comment != "" { + printf("//\n// %s\n", e.comment) + } + printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n", + varName, lowerVarName, lowerVarName, e.name) + if mibs[e.mib] { + log.Fatalf("MIB type %q declared multiple times.", e.mib) + } + printf("mib: identifier.%s,\n", e.mib) + printf("asciiSuperset: %t,\n", asciiSuperset) + printf("low: 0x%02x,\n", low) + printf("replacement: 0x%02x,\n", e.replacement) + + printf("decode: [256]utf8Enc{\n") + i, backMapping := 0, map[rune]byte{} + for _, c := range e.mapping { + if _, ok := backMapping[c]; !ok && c != utf8.RuneError { + backMapping[c] = byte(i) + } + var buf [8]byte + n := utf8.EncodeRune(buf[:], c) + if n > 3 { + panic(fmt.Sprintf("rune %q (%U) is too long", c, c)) + } + printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2]) + if i%2 == 1 { + printf("\n") + } + i++ + } + printf("},\n") + + printf("encode: [256]uint32{\n") + encode := make([]uint32, 0, 256) + for c, i := range backMapping { + encode = append(encode, uint32(i)<<24|uint32(c)) + } + sort.Sort(byRune(encode)) + for len(encode) < cap(encode) { + encode = append(encode, encode[len(encode)-1]) + } + for i, enc := range encode { + printf("0x%08x,", enc) + if i%8 == 7 { + printf("\n") + } + } + printf("},\n}\n") + + // Add an estimate of the size of a single Charmap{} struct value, which + // includes two 256 elem arrays of 4 bytes and some extra fields, which + // align to 3 uint64s on 64-bit architectures. + w.Size += 2*4*256 + 3*8 + } + // TODO: add proper line breaking. + printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n")) +} + +type byRune []uint32 + +func (b byRune) Len() int { return len(b) } +func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff } +func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/htmlindex/gen.go b/vendor/golang.org/x/text/encoding/htmlindex/gen.go new file mode 100644 index 000000000..ac6b4a77f --- /dev/null +++ b/vendor/golang.org/x/text/encoding/htmlindex/gen.go @@ -0,0 +1,173 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "strings" + + "golang.org/x/text/internal/gen" +) + +type group struct { + Encodings []struct { + Labels []string + Name string + } +} + +func main() { + gen.Init() + + r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") + var groups []group + if err := json.NewDecoder(r).Decode(&groups); err != nil { + log.Fatalf("Error reading encodings.json: %v", err) + } + + w := &bytes.Buffer{} + fmt.Fprintln(w, "type htmlEncoding byte") + fmt.Fprintln(w, "const (") + for i, g := range groups { + for _, e := range g.Encodings { + key := strings.ToLower(e.Name) + name := consts[key] + if name == "" { + log.Fatalf("No const defined for %s.", key) + } + if i == 0 { + fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) + } else { + fmt.Fprintf(w, "%s\n", name) + } + } + } + fmt.Fprintln(w, "numEncodings") + fmt.Fprint(w, ")\n\n") + + fmt.Fprintln(w, "var canonical = [numEncodings]string{") + for _, g := range groups { + for _, e := range g.Encodings { + fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) + } + } + fmt.Fprint(w, "}\n\n") + + fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") + for _, g := range groups { + for _, e := range g.Encodings { + for _, l := range e.Labels { + key := strings.ToLower(e.Name) + name := consts[key] + fmt.Fprintf(w, "%q: %s,\n", l, name) + } + } + } + fmt.Fprint(w, "}\n\n") + + var tags []string + fmt.Fprintln(w, "var localeMap = []htmlEncoding{") + for _, loc := range locales { + tags = append(tags, loc.tag) + fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) + } + fmt.Fprint(w, "}\n\n") + + fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) + + gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) +} + +// consts maps canonical encoding name to internal constant. +var consts = map[string]string{ + "utf-8": "utf8", + "ibm866": "ibm866", + "iso-8859-2": "iso8859_2", + "iso-8859-3": "iso8859_3", + "iso-8859-4": "iso8859_4", + "iso-8859-5": "iso8859_5", + "iso-8859-6": "iso8859_6", + "iso-8859-7": "iso8859_7", + "iso-8859-8": "iso8859_8", + "iso-8859-8-i": "iso8859_8I", + "iso-8859-10": "iso8859_10", + "iso-8859-13": "iso8859_13", + "iso-8859-14": "iso8859_14", + "iso-8859-15": "iso8859_15", + "iso-8859-16": "iso8859_16", + "koi8-r": "koi8r", + "koi8-u": "koi8u", + "macintosh": "macintosh", + "windows-874": "windows874", + "windows-1250": "windows1250", + "windows-1251": "windows1251", + "windows-1252": "windows1252", + "windows-1253": "windows1253", + "windows-1254": "windows1254", + "windows-1255": "windows1255", + "windows-1256": "windows1256", + "windows-1257": "windows1257", + "windows-1258": "windows1258", + "x-mac-cyrillic": "macintoshCyrillic", + "gbk": "gbk", + "gb18030": "gb18030", + // "hz-gb-2312": "hzgb2312", // Was removed from WhatWG + "big5": "big5", + "euc-jp": "eucjp", + "iso-2022-jp": "iso2022jp", + "shift_jis": "shiftJIS", + "euc-kr": "euckr", + "replacement": "replacement", + "utf-16be": "utf16be", + "utf-16le": "utf16le", + "x-user-defined": "xUserDefined", +} + +// locales is taken from +// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm. +var locales = []struct{ tag, name string }{ + // The default value. Explicitly state latin to benefit from the exact + // script option, while still making 1252 the default encoding for languages + // written in Latin script. + {"und_Latn", "windows-1252"}, + {"ar", "windows-1256"}, + {"ba", "windows-1251"}, + {"be", "windows-1251"}, + {"bg", "windows-1251"}, + {"cs", "windows-1250"}, + {"el", "iso-8859-7"}, + {"et", "windows-1257"}, + {"fa", "windows-1256"}, + {"he", "windows-1255"}, + {"hr", "windows-1250"}, + {"hu", "iso-8859-2"}, + {"ja", "shift_jis"}, + {"kk", "windows-1251"}, + {"ko", "euc-kr"}, + {"ku", "windows-1254"}, + {"ky", "windows-1251"}, + {"lt", "windows-1257"}, + {"lv", "windows-1257"}, + {"mk", "windows-1251"}, + {"pl", "iso-8859-2"}, + {"ru", "windows-1251"}, + {"sah", "windows-1251"}, + {"sk", "windows-1250"}, + {"sl", "iso-8859-2"}, + {"sr", "windows-1251"}, + {"tg", "windows-1251"}, + {"th", "windows-874"}, + {"tr", "windows-1254"}, + {"tt", "windows-1251"}, + {"uk", "windows-1251"}, + {"vi", "windows-1258"}, + {"zh-hans", "gb18030"}, + {"zh-hant", "big5"}, +} diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go new file mode 100644 index 000000000..26cfef9c6 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go @@ -0,0 +1,142 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "bytes" + "encoding/xml" + "fmt" + "io" + "log" + "strings" + + "golang.org/x/text/internal/gen" +) + +type registry struct { + XMLName xml.Name `xml:"registry"` + Updated string `xml:"updated"` + Registry []struct { + ID string `xml:"id,attr"` + Record []struct { + Name string `xml:"name"` + Xref []struct { + Type string `xml:"type,attr"` + Data string `xml:"data,attr"` + } `xml:"xref"` + Desc struct { + Data string `xml:",innerxml"` + // Any []struct { + // Data string `xml:",chardata"` + // } `xml:",any"` + // Data string `xml:",chardata"` + } `xml:"description,"` + MIB string `xml:"value"` + Alias []string `xml:"alias"` + MIME string `xml:"preferred_alias"` + } `xml:"record"` + } `xml:"registry"` +} + +func main() { + r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") + reg := ®istry{} + if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { + log.Fatalf("Error decoding charset registry: %v", err) + } + if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { + log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) + } + + w := &bytes.Buffer{} + fmt.Fprintf(w, "const (\n") + for _, rec := range reg.Registry[0].Record { + constName := "" + for _, a := range rec.Alias { + if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { + // Some of the constant definitions have comments in them. Strip those. + constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) + } + } + if constName == "" { + switch rec.MIB { + case "2085": + constName = "HZGB2312" // Not listed as alias for some reason. + default: + log.Fatalf("No cs alias defined for %s.", rec.MIB) + } + } + if rec.MIME != "" { + rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) + } + fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) + if len(rec.Desc.Data) > 0 { + fmt.Fprint(w, "// ") + d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) + inElem := true + attr := "" + for { + t, err := d.Token() + if err != nil { + if err != io.EOF { + log.Fatal(err) + } + break + } + switch x := t.(type) { + case xml.CharData: + attr = "" // Don't need attribute info. + a := bytes.Split([]byte(x), []byte("\n")) + for i, b := range a { + if b = bytes.TrimSpace(b); len(b) != 0 { + if !inElem && i > 0 { + fmt.Fprint(w, "\n// ") + } + inElem = false + fmt.Fprintf(w, "%s ", string(b)) + } + } + case xml.StartElement: + if x.Name.Local == "xref" { + inElem = true + use := false + for _, a := range x.Attr { + if a.Name.Local == "type" { + use = use || a.Value != "person" + } + if a.Name.Local == "data" && use { + // Patch up URLs to use https. From some links, the + // https version is different from the http one. + s := a.Value + s = strings.Replace(s, "http://", "https://", -1) + s = strings.Replace(s, "/unicode/", "/", -1) + attr = s + " " + } + } + } + case xml.EndElement: + inElem = false + fmt.Fprint(w, attr) + } + } + fmt.Fprint(w, "\n") + } + for _, x := range rec.Xref { + switch x.Type { + case "rfc": + fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) + case "uri": + fmt.Fprintf(w, "// Reference: %s\n", x.Data) + } + } + fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) + fmt.Fprintln(w) + } + fmt.Fprintln(w, ")") + + gen.WriteGoFile("mib.go", "identifier", w.Bytes()) +} diff --git a/vendor/golang.org/x/text/encoding/japanese/maketables.go b/vendor/golang.org/x/text/encoding/japanese/maketables.go new file mode 100644 index 000000000..023957a67 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/japanese/maketables.go @@ -0,0 +1,161 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +// TODO: Emoji extensions? +// https://www.unicode.org/faq/emoji_dingbats.html +// https://www.unicode.org/Public/UNIDATA/EmojiSources.txt + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +type entry struct { + jisCode, table int +} + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n") + fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n") + + reverse := [65536]entry{} + for i := range reverse { + reverse[i].table = -1 + } + + tables := []struct { + url string + name string + }{ + {"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"}, + {"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"}, + } + for i, table := range tables { + res, err := http.Get(table.url) + if err != nil { + log.Fatalf("%q: Get: %v", table.url, err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := 0, uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("%q: could not parse %q", table.url, s) + } + if x < 0 || 120*94 <= x { + log.Fatalf("%q: JIS code %d is out of range", table.url, x) + } + mapping[x] = y + if reverse[y].table == -1 { + reverse[y] = entry{jisCode: x, table: i} + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("%q: scanner error: %v", table.url, err) + } + + fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n", + table.name, table.name, table.url) + fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name) + for i, m := range mapping { + if m != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, m) + } + } + fmt.Printf("}\n\n") + } + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v.table == -1 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const (\n") + fmt.Printf("\tjis0208 = 1\n") + fmt.Printf("\tjis0212 = 2\n") + fmt.Printf("\tcodeMask = 0x7f\n") + fmt.Printf("\tcodeShift = 7\n") + fmt.Printf("\ttableShift = 14\n") + fmt.Printf(")\n\n") + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("//\n") + fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n") + fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n") + fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n") + fmt.Printf("// JIS code (94*j1 + j2) within that table.\n") + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x.table == -1 { + continue + } + fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n", + j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/korean/maketables.go b/vendor/golang.org/x/text/encoding/korean/maketables.go new file mode 100644 index 000000000..c84034fb6 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/korean/maketables.go @@ -0,0 +1,143 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") + fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") + + res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + reverse := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { + log.Fatalf("EUC-KR code %d is out of range", x) + } + mapping[x] = y + if reverse[y] == 0 { + c0, c1 := uint16(0), uint16(0) + if x < 178*(0xc7-0x81) { + c0 = uint16(x/178) + 0x81 + c1 = uint16(x % 178) + switch { + case c1 < 1*26: + c1 += 0x41 + case c1 < 2*26: + c1 += 0x47 + default: + c1 += 0x4d + } + } else { + x -= 178 * (0xc7 - 0x81) + c0 = uint16(x/94) + 0xc7 + c1 = uint16(x%94) + 0xa1 + } + reverse[y] = c0<<8 | c1 + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") + fmt.Printf("var decode = [...]uint16{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go new file mode 100644 index 000000000..55016c786 --- /dev/null +++ b/vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go @@ -0,0 +1,161 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") + fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") + + printGB18030() + printGBK() +} + +func printGB18030() { + res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") + fmt.Printf("var gb18030 = [...][2]uint16{\n") + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint32(0), uint32(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0x10000 && y < 0x10000 { + fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) + } + } + fmt.Printf("}\n\n") +} + +func printGBK() { + res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint16{} + reverse := [65536]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint16(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 126*190 <= x { + log.Fatalf("GBK code %d is out of range", x) + } + mapping[x] = y + if reverse[y] == 0 { + c0, c1 := x/190, x%190 + if c1 >= 0x3f { + c1++ + } + reverse[y] = (0x81+c0)<<8 | (0x40 + c1) + } + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") + fmt.Printf("var decode = [...]uint16{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%04X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go new file mode 100644 index 000000000..cf7fdb31a --- /dev/null +++ b/vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go @@ -0,0 +1,140 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This program generates tables.go: +// go run maketables.go | gofmt > tables.go + +import ( + "bufio" + "fmt" + "log" + "net/http" + "sort" + "strings" +) + +func main() { + fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") + fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") + fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") + + res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") + if err != nil { + log.Fatalf("Get: %v", err) + } + defer res.Body.Close() + + mapping := [65536]uint32{} + reverse := [65536 * 4]uint16{} + + scanner := bufio.NewScanner(res.Body) + for scanner.Scan() { + s := strings.TrimSpace(scanner.Text()) + if s == "" || s[0] == '#' { + continue + } + x, y := uint16(0), uint32(0) + if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { + log.Fatalf("could not parse %q", s) + } + if x < 0 || 126*157 <= x { + log.Fatalf("Big5 code %d is out of range", x) + } + mapping[x] = y + + // The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that + // "The index pointer for code point in index is the first pointer + // corresponding to code point in index", which would normally mean + // that the code below should be guarded by "if reverse[y] == 0", but + // last instead of first seems to match the behavior of + // "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in + // http://encoding.spec.whatwg.org/index-big5.txt, as index 2148 + // (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc") + // and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc". + c0, c1 := x/157, x%157 + if c1 < 0x3f { + c1 += 0x40 + } else { + c1 += 0x62 + } + reverse[y] = (0x81+c0)<<8 | c1 + } + if err := scanner.Err(); err != nil { + log.Fatalf("scanner error: %v", err) + } + + fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") + fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") + fmt.Printf("var decode = [...]uint32{\n") + for i, v := range mapping { + if v != 0 { + fmt.Printf("\t%d: 0x%08X,\n", i, v) + } + } + fmt.Printf("}\n\n") + + // Any run of at least separation continuous zero entries in the reverse map will + // be a separate encode table. + const separation = 1024 + + intervals := []interval(nil) + low, high := -1, -1 + for i, v := range reverse { + if v == 0 { + continue + } + if low < 0 { + low = i + } else if i-high >= separation { + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + low = i + } + high = i + 1 + } + if high >= 0 { + intervals = append(intervals, interval{low, high}) + } + sort.Sort(byDecreasingLength(intervals)) + + fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) + fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") + fmt.Printf("// sorted by decreasing length.\n") + for i, v := range intervals { + fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) + } + fmt.Printf("\n") + + for i, v := range intervals { + fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) + fmt.Printf("var encode%d = [...]uint16{\n", i) + for j := v.low; j < v.high; j++ { + x := reverse[j] + if x == 0 { + continue + } + fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) + } + fmt.Printf("}\n\n") + } +} + +// interval is a half-open interval [low, high). +type interval struct { + low, high int +} + +func (i interval) len() int { return i.high - i.low } + +// byDecreasingLength sorts intervals by decreasing length. +type byDecreasingLength []interval + +func (b byDecreasingLength) Len() int { return len(b) } +func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } +func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/vendor/golang.org/x/text/internal/language/compact/gen.go b/vendor/golang.org/x/text/internal/language/compact/gen.go new file mode 100644 index 000000000..0c36a052f --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen.go @@ -0,0 +1,64 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Language tag table generator. +// Data read from the web. + +package main + +import ( + "flag" + "fmt" + "log" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/unicode/cldr" +) + +var ( + test = flag.Bool("test", + false, + "test existing tables; can be used to compare web data with package data.") + outputFile = flag.String("output", + "tables.go", + "output file for generated tables") +) + +func main() { + gen.Init() + + w := gen.NewCodeWriter() + defer w.WriteGoFile("tables.go", "compact") + + fmt.Fprintln(w, `import "golang.org/x/text/internal/language"`) + + b := newBuilder(w) + gen.WriteCLDRVersion(w) + + b.writeCompactIndex() +} + +type builder struct { + w *gen.CodeWriter + data *cldr.CLDR + supp *cldr.SupplementalData +} + +func newBuilder(w *gen.CodeWriter) *builder { + r := gen.OpenCLDRCoreZip() + defer r.Close() + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + if err != nil { + log.Fatal(err) + } + b := builder{ + w: w, + data: data, + supp: data.Supplemental(), + } + return &b +} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_index.go b/vendor/golang.org/x/text/internal/language/compact/gen_index.go new file mode 100644 index 000000000..136cefaf0 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen_index.go @@ -0,0 +1,113 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +// This file generates derivative tables based on the language package itself. + +import ( + "fmt" + "log" + "sort" + "strings" + + "golang.org/x/text/internal/language" +) + +// Compact indices: +// Note -va-X variants only apply to localization variants. +// BCP variants only ever apply to language. +// The only ambiguity between tags is with regions. + +func (b *builder) writeCompactIndex() { + // Collect all language tags for which we have any data in CLDR. + m := map[language.Tag]bool{} + for _, lang := range b.data.Locales() { + // We include all locales unconditionally to be consistent with en_US. + // We want en_US, even though it has no data associated with it. + + // TODO: put any of the languages for which no data exists at the end + // of the index. This allows all components based on ICU to use that + // as the cutoff point. + // if x := data.RawLDML(lang); false || + // x.LocaleDisplayNames != nil || + // x.Characters != nil || + // x.Delimiters != nil || + // x.Measurement != nil || + // x.Dates != nil || + // x.Numbers != nil || + // x.Units != nil || + // x.ListPatterns != nil || + // x.Collations != nil || + // x.Segmentations != nil || + // x.Rbnf != nil || + // x.Annotations != nil || + // x.Metadata != nil { + + // TODO: support POSIX natively, albeit non-standard. + tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1)) + m[tag] = true + // } + } + + // TODO: plural rules are also defined for the deprecated tags: + // iw mo sh tl + // Consider removing these as compact tags. + + // Include locales for plural rules, which uses a different structure. + for _, plurals := range b.supp.Plurals { + for _, rules := range plurals.PluralRules { + for _, lang := range strings.Split(rules.Locales, " ") { + m[language.Make(lang)] = true + } + } + } + + var coreTags []language.CompactCoreInfo + var special []string + + for t := range m { + if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { + log.Fatalf("Unexpected extension %v in %v", x, t) + } + if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { + cci, ok := language.GetCompactCore(t) + if !ok { + log.Fatalf("Locale for non-basic language %q", t) + } + coreTags = append(coreTags, cci) + } else { + special = append(special, t.String()) + } + } + + w := b.w + + sort.Slice(coreTags, func(i, j int) bool { return coreTags[i] < coreTags[j] }) + sort.Strings(special) + + w.WriteComment(` + NumCompactTags is the number of common tags. The maximum tag is + NumCompactTags-1.`) + w.WriteConst("NumCompactTags", len(m)) + + fmt.Fprintln(w, "const (") + for i, t := range coreTags { + fmt.Fprintf(w, "%s ID = %d\n", ident(t.Tag().String()), i) + } + for i, t := range special { + fmt.Fprintf(w, "%s ID = %d\n", ident(t), i+len(coreTags)) + } + fmt.Fprintln(w, ")") + + w.WriteVar("coreTags", coreTags) + + w.WriteConst("specialTagsStr", strings.Join(special, " ")) +} + +func ident(s string) string { + return strings.Replace(s, "-", "", -1) + "Index" +} diff --git a/vendor/golang.org/x/text/internal/language/compact/gen_parents.go b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go new file mode 100644 index 000000000..9543d5832 --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/compact/gen_parents.go @@ -0,0 +1,54 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "log" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/language" + "golang.org/x/text/internal/language/compact" + "golang.org/x/text/unicode/cldr" +) + +func main() { + r := gen.OpenCLDRCoreZip() + defer r.Close() + + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + if err != nil { + log.Fatalf("DecodeZip: %v", err) + } + + w := gen.NewCodeWriter() + defer w.WriteGoFile("parents.go", "compact") + + // Create parents table. + type ID uint16 + parents := make([]ID, compact.NumCompactTags) + for _, loc := range data.Locales() { + tag := language.MustParse(loc) + index, ok := compact.FromTag(tag) + if !ok { + continue + } + parentIndex := compact.ID(0) // und + for p := tag.Parent(); p != language.Und; p = p.Parent() { + if x, ok := compact.FromTag(p); ok { + parentIndex = x + break + } + } + parents[index] = ID(parentIndex) + } + + w.WriteComment(` + parents maps a compact index of a tag to the compact index of the parent of + this tag.`) + w.WriteVar("parents", parents) +} diff --git a/vendor/golang.org/x/text/internal/language/gen.go b/vendor/golang.org/x/text/internal/language/gen.go new file mode 100644 index 000000000..cdcc7febc --- /dev/null +++ b/vendor/golang.org/x/text/internal/language/gen.go @@ -0,0 +1,1520 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Language tag table generator. +// Data read from the web. + +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/tag" + "golang.org/x/text/unicode/cldr" +) + +var ( + test = flag.Bool("test", + false, + "test existing tables; can be used to compare web data with package data.") + outputFile = flag.String("output", + "tables.go", + "output file for generated tables") +) + +var comment = []string{ + ` +lang holds an alphabetically sorted list of ISO-639 language identifiers. +All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag. +For 2-byte language identifiers, the two successive bytes have the following meaning: + - if the first letter of the 2- and 3-letter ISO codes are the same: + the second and third letter of the 3-letter ISO code. + - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3. +For 3-byte language identifiers the 4th byte is 0.`, + ` +langNoIndex is a bit vector of all 3-letter language codes that are not used as an index +in lookup tables. The language ids for these language codes are derived directly +from the letters and are not consecutive.`, + ` +altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives +to 2-letter language codes that cannot be derived using the method described above. +Each 3-letter code is followed by its 1-byte langID.`, + ` +altLangIndex is used to convert indexes in altLangISO3 to langIDs.`, + ` +AliasMap maps langIDs to their suggested replacements.`, + ` +script is an alphabetically sorted list of ISO 15924 codes. The index +of the script in the string, divided by 4, is the internal scriptID.`, + ` +isoRegionOffset needs to be added to the index of regionISO to obtain the regionID +for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for +the UN.M49 codes used for groups.)`, + ` +regionISO holds a list of alphabetically sorted 2-letter ISO region codes. +Each 2-letter codes is followed by two bytes with the following meaning: + - [A-Z}{2}: the first letter of the 2-letter code plus these two + letters form the 3-letter ISO code. + - 0, n: index into altRegionISO3.`, + ` +regionTypes defines the status of a region for various standards.`, + ` +m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are +codes indicating collections of regions.`, + ` +m49Index gives indexes into fromM49 based on the three most significant bits +of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in + fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]] +for an entry where the first 7 bits match the 7 lsb of the UN.M49 code. +The region code is stored in the 9 lsb of the indexed value.`, + ` +fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details.`, + ` +altRegionISO3 holds a list of 3-letter region codes that cannot be +mapped to 2-letter codes using the default algorithm. This is a short list.`, + ` +altRegionIDs holds a list of regionIDs the positions of which match those +of the 3-letter ISO codes in altRegionISO3.`, + ` +variantNumSpecialized is the number of specialized variants in variants.`, + ` +suppressScript is an index from langID to the dominant script for that language, +if it exists. If a script is given, it should be suppressed from the language tag.`, + ` +likelyLang is a lookup table, indexed by langID, for the most likely +scripts and regions given incomplete information. If more entries exist for a +given language, region and script are the index and size respectively +of the list in likelyLangList.`, + ` +likelyLangList holds lists info associated with likelyLang.`, + ` +likelyRegion is a lookup table, indexed by regionID, for the most likely +languages and scripts given incomplete information. If more entries exist +for a given regionID, lang and script are the index and size respectively +of the list in likelyRegionList. +TODO: exclude containers and user-definable regions from the list.`, + ` +likelyRegionList holds lists info associated with likelyRegion.`, + ` +likelyScript is a lookup table, indexed by scriptID, for the most likely +languages and regions given a script.`, + ` +nRegionGroups is the number of region groups.`, + ` +regionInclusion maps region identifiers to sets of regions in regionInclusionBits, +where each set holds all groupings that are directly connected in a region +containment graph.`, + ` +regionInclusionBits is an array of bit vectors where every vector represents +a set of region groupings. These sets are used to compute the distance +between two regions for the purpose of language matching.`, + ` +regionInclusionNext marks, for each entry in regionInclusionBits, the set of +all groups that are reachable from the groups set in the respective entry.`, +} + +// TODO: consider changing some of these structures to tries. This can reduce +// memory, but may increase the need for memory allocations. This could be +// mitigated if we can piggyback on language tags for common cases. + +func failOnError(e error) { + if e != nil { + log.Panic(e) + } +} + +type setType int + +const ( + Indexed setType = 1 + iota // all elements must be of same size + Linear +) + +type stringSet struct { + s []string + sorted, frozen bool + + // We often need to update values after the creation of an index is completed. + // We include a convenience map for keeping track of this. + update map[string]string + typ setType // used for checking. +} + +func (ss *stringSet) clone() stringSet { + c := *ss + c.s = append([]string(nil), c.s...) + return c +} + +func (ss *stringSet) setType(t setType) { + if ss.typ != t && ss.typ != 0 { + log.Panicf("type %d cannot be assigned as it was already %d", t, ss.typ) + } +} + +// parse parses a whitespace-separated string and initializes ss with its +// components. +func (ss *stringSet) parse(s string) { + scan := bufio.NewScanner(strings.NewReader(s)) + scan.Split(bufio.ScanWords) + for scan.Scan() { + ss.add(scan.Text()) + } +} + +func (ss *stringSet) assertChangeable() { + if ss.frozen { + log.Panic("attempt to modify a frozen stringSet") + } +} + +func (ss *stringSet) add(s string) { + ss.assertChangeable() + ss.s = append(ss.s, s) + ss.sorted = ss.frozen +} + +func (ss *stringSet) freeze() { + ss.compact() + ss.frozen = true +} + +func (ss *stringSet) compact() { + if ss.sorted { + return + } + a := ss.s + sort.Strings(a) + k := 0 + for i := 1; i < len(a); i++ { + if a[k] != a[i] { + a[k+1] = a[i] + k++ + } + } + ss.s = a[:k+1] + ss.sorted = ss.frozen +} + +type funcSorter struct { + fn func(a, b string) bool + sort.StringSlice +} + +func (s funcSorter) Less(i, j int) bool { + return s.fn(s.StringSlice[i], s.StringSlice[j]) +} + +func (ss *stringSet) sortFunc(f func(a, b string) bool) { + ss.compact() + sort.Sort(funcSorter{f, sort.StringSlice(ss.s)}) +} + +func (ss *stringSet) remove(s string) { + ss.assertChangeable() + if i, ok := ss.find(s); ok { + copy(ss.s[i:], ss.s[i+1:]) + ss.s = ss.s[:len(ss.s)-1] + } +} + +func (ss *stringSet) replace(ol, nu string) { + ss.s[ss.index(ol)] = nu + ss.sorted = ss.frozen +} + +func (ss *stringSet) index(s string) int { + ss.setType(Indexed) + i, ok := ss.find(s) + if !ok { + if i < len(ss.s) { + log.Panicf("find: item %q is not in list. Closest match is %q.", s, ss.s[i]) + } + log.Panicf("find: item %q is not in list", s) + + } + return i +} + +func (ss *stringSet) find(s string) (int, bool) { + ss.compact() + i := sort.SearchStrings(ss.s, s) + return i, i != len(ss.s) && ss.s[i] == s +} + +func (ss *stringSet) slice() []string { + ss.compact() + return ss.s +} + +func (ss *stringSet) updateLater(v, key string) { + if ss.update == nil { + ss.update = map[string]string{} + } + ss.update[v] = key +} + +// join joins the string and ensures that all entries are of the same length. +func (ss *stringSet) join() string { + ss.setType(Indexed) + n := len(ss.s[0]) + for _, s := range ss.s { + if len(s) != n { + log.Panicf("join: not all entries are of the same length: %q", s) + } + } + ss.s = append(ss.s, strings.Repeat("\xff", n)) + return strings.Join(ss.s, "") +} + +// ianaEntry holds information for an entry in the IANA Language Subtag Repository. +// All types use the same entry. +// See http://tools.ietf.org/html/bcp47#section-5.1 for a description of the various +// fields. +type ianaEntry struct { + typ string + description []string + scope string + added string + preferred string + deprecated string + suppressScript string + macro string + prefix []string +} + +type builder struct { + w *gen.CodeWriter + hw io.Writer // MultiWriter for w and w.Hash + data *cldr.CLDR + supp *cldr.SupplementalData + + // indices + locale stringSet // common locales + lang stringSet // canonical language ids (2 or 3 letter ISO codes) with data + langNoIndex stringSet // 3-letter ISO codes with no associated data + script stringSet // 4-letter ISO codes + region stringSet // 2-letter ISO or 3-digit UN M49 codes + variant stringSet // 4-8-alphanumeric variant code. + + // Region codes that are groups with their corresponding group IDs. + groups map[int]index + + // langInfo + registry map[string]*ianaEntry +} + +type index uint + +func newBuilder(w *gen.CodeWriter) *builder { + r := gen.OpenCLDRCoreZip() + defer r.Close() + d := &cldr.Decoder{} + data, err := d.DecodeZip(r) + failOnError(err) + b := builder{ + w: w, + hw: io.MultiWriter(w, w.Hash), + data: data, + supp: data.Supplemental(), + } + b.parseRegistry() + return &b +} + +func (b *builder) parseRegistry() { + r := gen.OpenIANAFile("assignments/language-subtag-registry") + defer r.Close() + b.registry = make(map[string]*ianaEntry) + + scan := bufio.NewScanner(r) + scan.Split(bufio.ScanWords) + var record *ianaEntry + for more := scan.Scan(); more; { + key := scan.Text() + more = scan.Scan() + value := scan.Text() + switch key { + case "Type:": + record = &ianaEntry{typ: value} + case "Subtag:", "Tag:": + if s := strings.SplitN(value, "..", 2); len(s) > 1 { + for a := s[0]; a <= s[1]; a = inc(a) { + b.addToRegistry(a, record) + } + } else { + b.addToRegistry(value, record) + } + case "Suppress-Script:": + record.suppressScript = value + case "Added:": + record.added = value + case "Deprecated:": + record.deprecated = value + case "Macrolanguage:": + record.macro = value + case "Preferred-Value:": + record.preferred = value + case "Prefix:": + record.prefix = append(record.prefix, value) + case "Scope:": + record.scope = value + case "Description:": + buf := []byte(value) + for more = scan.Scan(); more; more = scan.Scan() { + b := scan.Bytes() + if b[0] == '%' || b[len(b)-1] == ':' { + break + } + buf = append(buf, ' ') + buf = append(buf, b...) + } + record.description = append(record.description, string(buf)) + continue + default: + continue + } + more = scan.Scan() + } + if scan.Err() != nil { + log.Panic(scan.Err()) + } +} + +func (b *builder) addToRegistry(key string, entry *ianaEntry) { + if info, ok := b.registry[key]; ok { + if info.typ != "language" || entry.typ != "extlang" { + log.Fatalf("parseRegistry: tag %q already exists", key) + } + } else { + b.registry[key] = entry + } +} + +var commentIndex = make(map[string]string) + +func init() { + for _, s := range comment { + key := strings.TrimSpace(strings.SplitN(s, " ", 2)[0]) + commentIndex[key] = s + } +} + +func (b *builder) comment(name string) { + if s := commentIndex[name]; len(s) > 0 { + b.w.WriteComment(s) + } else { + fmt.Fprintln(b.w) + } +} + +func (b *builder) pf(f string, x ...interface{}) { + fmt.Fprintf(b.hw, f, x...) + fmt.Fprint(b.hw, "\n") +} + +func (b *builder) p(x ...interface{}) { + fmt.Fprintln(b.hw, x...) +} + +func (b *builder) addSize(s int) { + b.w.Size += s + b.pf("// Size: %d bytes", s) +} + +func (b *builder) writeConst(name string, x interface{}) { + b.comment(name) + b.w.WriteConst(name, x) +} + +// writeConsts computes f(v) for all v in values and writes the results +// as constants named _v to a single constant block. +func (b *builder) writeConsts(f func(string) int, values ...string) { + b.pf("const (") + for _, v := range values { + b.pf("\t_%s = %v", v, f(v)) + } + b.pf(")") +} + +// writeType writes the type of the given value, which must be a struct. +func (b *builder) writeType(value interface{}) { + b.comment(reflect.TypeOf(value).Name()) + b.w.WriteType(value) +} + +func (b *builder) writeSlice(name string, ss interface{}) { + b.writeSliceAddSize(name, 0, ss) +} + +func (b *builder) writeSliceAddSize(name string, extraSize int, ss interface{}) { + b.comment(name) + b.w.Size += extraSize + v := reflect.ValueOf(ss) + t := v.Type().Elem() + b.pf("// Size: %d bytes, %d elements", v.Len()*int(t.Size())+extraSize, v.Len()) + + fmt.Fprintf(b.w, "var %s = ", name) + b.w.WriteArray(ss) + b.p() +} + +type FromTo struct { + From, To uint16 +} + +func (b *builder) writeSortedMap(name string, ss *stringSet, index func(s string) uint16) { + ss.sortFunc(func(a, b string) bool { + return index(a) < index(b) + }) + m := []FromTo{} + for _, s := range ss.s { + m = append(m, FromTo{index(s), index(ss.update[s])}) + } + b.writeSlice(name, m) +} + +const base = 'z' - 'a' + 1 + +func strToInt(s string) uint { + v := uint(0) + for i := 0; i < len(s); i++ { + v *= base + v += uint(s[i] - 'a') + } + return v +} + +// converts the given integer to the original ASCII string passed to strToInt. +// len(s) must match the number of characters obtained. +func intToStr(v uint, s []byte) { + for i := len(s) - 1; i >= 0; i-- { + s[i] = byte(v%base) + 'a' + v /= base + } +} + +func (b *builder) writeBitVector(name string, ss []string) { + vec := make([]uint8, int(math.Ceil(math.Pow(base, float64(len(ss[0])))/8))) + for _, s := range ss { + v := strToInt(s) + vec[v/8] |= 1 << (v % 8) + } + b.writeSlice(name, vec) +} + +// TODO: convert this type into a list or two-stage trie. +func (b *builder) writeMapFunc(name string, m map[string]string, f func(string) uint16) { + b.comment(name) + v := reflect.ValueOf(m) + sz := v.Len() * (2 + int(v.Type().Key().Size())) + for _, k := range m { + sz += len(k) + } + b.addSize(sz) + keys := []string{} + b.pf(`var %s = map[string]uint16{`, name) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + b.pf("\t%q: %v,", k, f(m[k])) + } + b.p("}") +} + +func (b *builder) writeMap(name string, m interface{}) { + b.comment(name) + v := reflect.ValueOf(m) + sz := v.Len() * (2 + int(v.Type().Key().Size()) + int(v.Type().Elem().Size())) + b.addSize(sz) + f := strings.FieldsFunc(fmt.Sprintf("%#v", m), func(r rune) bool { + return strings.IndexRune("{}, ", r) != -1 + }) + sort.Strings(f[1:]) + b.pf(`var %s = %s{`, name, f[0]) + for _, kv := range f[1:] { + b.pf("\t%s,", kv) + } + b.p("}") +} + +func (b *builder) langIndex(s string) uint16 { + if s == "und" { + return 0 + } + if i, ok := b.lang.find(s); ok { + return uint16(i) + } + return uint16(strToInt(s)) + uint16(len(b.lang.s)) +} + +// inc advances the string to its lexicographical successor. +func inc(s string) string { + const maxTagLength = 4 + var buf [maxTagLength]byte + intToStr(strToInt(strings.ToLower(s))+1, buf[:len(s)]) + for i := 0; i < len(s); i++ { + if s[i] <= 'Z' { + buf[i] -= 'a' - 'A' + } + } + return string(buf[:len(s)]) +} + +func (b *builder) parseIndices() { + meta := b.supp.Metadata + + for k, v := range b.registry { + var ss *stringSet + switch v.typ { + case "language": + if len(k) == 2 || v.suppressScript != "" || v.scope == "special" { + b.lang.add(k) + continue + } else { + ss = &b.langNoIndex + } + case "region": + ss = &b.region + case "script": + ss = &b.script + case "variant": + ss = &b.variant + default: + continue + } + ss.add(k) + } + // Include any language for which there is data. + for _, lang := range b.data.Locales() { + if x := b.data.RawLDML(lang); false || + x.LocaleDisplayNames != nil || + x.Characters != nil || + x.Delimiters != nil || + x.Measurement != nil || + x.Dates != nil || + x.Numbers != nil || + x.Units != nil || + x.ListPatterns != nil || + x.Collations != nil || + x.Segmentations != nil || + x.Rbnf != nil || + x.Annotations != nil || + x.Metadata != nil { + + from := strings.Split(lang, "_") + if lang := from[0]; lang != "root" { + b.lang.add(lang) + } + } + } + // Include locales for plural rules, which uses a different structure. + for _, plurals := range b.data.Supplemental().Plurals { + for _, rules := range plurals.PluralRules { + for _, lang := range strings.Split(rules.Locales, " ") { + if lang = strings.Split(lang, "_")[0]; lang != "root" { + b.lang.add(lang) + } + } + } + } + // Include languages in likely subtags. + for _, m := range b.supp.LikelySubtags.LikelySubtag { + from := strings.Split(m.From, "_") + b.lang.add(from[0]) + } + // Include ISO-639 alpha-3 bibliographic entries. + for _, a := range meta.Alias.LanguageAlias { + if a.Reason == "bibliographic" { + b.langNoIndex.add(a.Type) + } + } + // Include regions in territoryAlias (not all are in the IANA registry!) + for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { + if len(reg.Type) == 2 { + b.region.add(reg.Type) + } + } + + for _, s := range b.lang.s { + if len(s) == 3 { + b.langNoIndex.remove(s) + } + } + b.writeConst("NumLanguages", len(b.lang.slice())+len(b.langNoIndex.slice())) + b.writeConst("NumScripts", len(b.script.slice())) + b.writeConst("NumRegions", len(b.region.slice())) + + // Add dummy codes at the start of each list to represent "unspecified". + b.lang.add("---") + b.script.add("----") + b.region.add("---") + + // common locales + b.locale.parse(meta.DefaultContent.Locales) +} + +// TODO: region inclusion data will probably not be use used in future matchers. + +func (b *builder) computeRegionGroups() { + b.groups = make(map[int]index) + + // Create group indices. + for i := 1; b.region.s[i][0] < 'A'; i++ { // Base M49 indices on regionID. + b.groups[i] = index(len(b.groups)) + } + for _, g := range b.supp.TerritoryContainment.Group { + // Skip UN and EURO zone as they are flattening the containment + // relationship. + if g.Type == "EZ" || g.Type == "UN" { + continue + } + group := b.region.index(g.Type) + if _, ok := b.groups[group]; !ok { + b.groups[group] = index(len(b.groups)) + } + } + if len(b.groups) > 64 { + log.Fatalf("only 64 groups supported, found %d", len(b.groups)) + } + b.writeConst("nRegionGroups", len(b.groups)) +} + +var langConsts = []string{ + "af", "am", "ar", "az", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "es", + "et", "fa", "fi", "fil", "fr", "gu", "he", "hi", "hr", "hu", "hy", "id", "is", + "it", "ja", "ka", "kk", "km", "kn", "ko", "ky", "lo", "lt", "lv", "mk", "ml", + "mn", "mo", "mr", "ms", "mul", "my", "nb", "ne", "nl", "no", "pa", "pl", "pt", + "ro", "ru", "sh", "si", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", + "tl", "tn", "tr", "uk", "ur", "uz", "vi", "zh", "zu", + + // constants for grandfathered tags (if not already defined) + "jbo", "ami", "bnn", "hak", "tlh", "lb", "nv", "pwn", "tao", "tay", "tsu", + "nn", "sfb", "vgt", "sgg", "cmn", "nan", "hsn", +} + +// writeLanguage generates all tables needed for language canonicalization. +func (b *builder) writeLanguage() { + meta := b.supp.Metadata + + b.writeConst("nonCanonicalUnd", b.lang.index("und")) + b.writeConsts(func(s string) int { return int(b.langIndex(s)) }, langConsts...) + b.writeConst("langPrivateStart", b.langIndex("qaa")) + b.writeConst("langPrivateEnd", b.langIndex("qtz")) + + // Get language codes that need to be mapped (overlong 3-letter codes, + // deprecated 2-letter codes, legacy and grandfathered tags.) + langAliasMap := stringSet{} + aliasTypeMap := map[string]AliasType{} + + // altLangISO3 get the alternative ISO3 names that need to be mapped. + altLangISO3 := stringSet{} + // Add dummy start to avoid the use of index 0. + altLangISO3.add("---") + altLangISO3.updateLater("---", "aa") + + lang := b.lang.clone() + for _, a := range meta.Alias.LanguageAlias { + if a.Replacement == "" { + a.Replacement = "und" + } + // TODO: support mapping to tags + repl := strings.SplitN(a.Replacement, "_", 2)[0] + if a.Reason == "overlong" { + if len(a.Replacement) == 2 && len(a.Type) == 3 { + lang.updateLater(a.Replacement, a.Type) + } + } else if len(a.Type) <= 3 { + switch a.Reason { + case "macrolanguage": + aliasTypeMap[a.Type] = Macro + case "deprecated": + // handled elsewhere + continue + case "bibliographic", "legacy": + if a.Type == "no" { + continue + } + aliasTypeMap[a.Type] = Legacy + default: + log.Fatalf("new %s alias: %s", a.Reason, a.Type) + } + langAliasMap.add(a.Type) + langAliasMap.updateLater(a.Type, repl) + } + } + // Manually add the mapping of "nb" (Norwegian) to its macro language. + // This can be removed if CLDR adopts this change. + langAliasMap.add("nb") + langAliasMap.updateLater("nb", "no") + aliasTypeMap["nb"] = Macro + + for k, v := range b.registry { + // Also add deprecated values for 3-letter ISO codes, which CLDR omits. + if v.typ == "language" && v.deprecated != "" && v.preferred != "" { + langAliasMap.add(k) + langAliasMap.updateLater(k, v.preferred) + aliasTypeMap[k] = Deprecated + } + } + // Fix CLDR mappings. + lang.updateLater("tl", "tgl") + lang.updateLater("sh", "hbs") + lang.updateLater("mo", "mol") + lang.updateLater("no", "nor") + lang.updateLater("tw", "twi") + lang.updateLater("nb", "nob") + lang.updateLater("ak", "aka") + lang.updateLater("bh", "bih") + + // Ensure that each 2-letter code is matched with a 3-letter code. + for _, v := range lang.s[1:] { + s, ok := lang.update[v] + if !ok { + if s, ok = lang.update[langAliasMap.update[v]]; !ok { + continue + } + lang.update[v] = s + } + if v[0] != s[0] { + altLangISO3.add(s) + altLangISO3.updateLater(s, v) + } + } + + // Complete canonicalized language tags. + lang.freeze() + for i, v := range lang.s { + // We can avoid these manual entries by using the IANA registry directly. + // Seems easier to update the list manually, as changes are rare. + // The panic in this loop will trigger if we miss an entry. + add := "" + if s, ok := lang.update[v]; ok { + if s[0] == v[0] { + add = s[1:] + } else { + add = string([]byte{0, byte(altLangISO3.index(s))}) + } + } else if len(v) == 3 { + add = "\x00" + } else { + log.Panicf("no data for long form of %q", v) + } + lang.s[i] += add + } + b.writeConst("lang", tag.Index(lang.join())) + + b.writeConst("langNoIndexOffset", len(b.lang.s)) + + // space of all valid 3-letter language identifiers. + b.writeBitVector("langNoIndex", b.langNoIndex.slice()) + + altLangIndex := []uint16{} + for i, s := range altLangISO3.slice() { + altLangISO3.s[i] += string([]byte{byte(len(altLangIndex))}) + if i > 0 { + idx := b.lang.index(altLangISO3.update[s]) + altLangIndex = append(altLangIndex, uint16(idx)) + } + } + b.writeConst("altLangISO3", tag.Index(altLangISO3.join())) + b.writeSlice("altLangIndex", altLangIndex) + + b.writeSortedMap("AliasMap", &langAliasMap, b.langIndex) + types := make([]AliasType, len(langAliasMap.s)) + for i, s := range langAliasMap.s { + types[i] = aliasTypeMap[s] + } + b.writeSlice("AliasTypes", types) +} + +var scriptConsts = []string{ + "Latn", "Hani", "Hans", "Hant", "Qaaa", "Qaai", "Qabx", "Zinh", "Zyyy", + "Zzzz", +} + +func (b *builder) writeScript() { + b.writeConsts(b.script.index, scriptConsts...) + b.writeConst("script", tag.Index(b.script.join())) + + supp := make([]uint8, len(b.lang.slice())) + for i, v := range b.lang.slice()[1:] { + if sc := b.registry[v].suppressScript; sc != "" { + supp[i+1] = uint8(b.script.index(sc)) + } + } + b.writeSlice("suppressScript", supp) + + // There is only one deprecated script in CLDR. This value is hard-coded. + // We check here if the code must be updated. + for _, a := range b.supp.Metadata.Alias.ScriptAlias { + if a.Type != "Qaai" { + log.Panicf("unexpected deprecated stript %q", a.Type) + } + } +} + +func parseM49(s string) int16 { + if len(s) == 0 { + return 0 + } + v, err := strconv.ParseUint(s, 10, 10) + failOnError(err) + return int16(v) +} + +var regionConsts = []string{ + "001", "419", "BR", "CA", "ES", "GB", "MD", "PT", "UK", "US", + "ZZ", "XA", "XC", "XK", // Unofficial tag for Kosovo. +} + +func (b *builder) writeRegion() { + b.writeConsts(b.region.index, regionConsts...) + + isoOffset := b.region.index("AA") + m49map := make([]int16, len(b.region.slice())) + fromM49map := make(map[int16]int) + altRegionISO3 := "" + altRegionIDs := []uint16{} + + b.writeConst("isoRegionOffset", isoOffset) + + // 2-letter region lookup and mapping to numeric codes. + regionISO := b.region.clone() + regionISO.s = regionISO.s[isoOffset:] + regionISO.sorted = false + + regionTypes := make([]byte, len(b.region.s)) + + // Is the region valid BCP 47? + for s, e := range b.registry { + if len(s) == 2 && s == strings.ToUpper(s) { + i := b.region.index(s) + for _, d := range e.description { + if strings.Contains(d, "Private use") { + regionTypes[i] = iso3166UserAssigned + } + } + regionTypes[i] |= bcp47Region + } + } + + // Is the region a valid ccTLD? + r := gen.OpenIANAFile("domains/root/db") + defer r.Close() + + buf, err := ioutil.ReadAll(r) + failOnError(err) + re := regexp.MustCompile(`"/domains/root/db/([a-z]{2}).html"`) + for _, m := range re.FindAllSubmatch(buf, -1) { + i := b.region.index(strings.ToUpper(string(m[1]))) + regionTypes[i] |= ccTLD + } + + b.writeSlice("regionTypes", regionTypes) + + iso3Set := make(map[string]int) + update := func(iso2, iso3 string) { + i := regionISO.index(iso2) + if j, ok := iso3Set[iso3]; !ok && iso3[0] == iso2[0] { + regionISO.s[i] += iso3[1:] + iso3Set[iso3] = -1 + } else { + if ok && j >= 0 { + regionISO.s[i] += string([]byte{0, byte(j)}) + } else { + iso3Set[iso3] = len(altRegionISO3) + regionISO.s[i] += string([]byte{0, byte(len(altRegionISO3))}) + altRegionISO3 += iso3 + altRegionIDs = append(altRegionIDs, uint16(isoOffset+i)) + } + } + } + for _, tc := range b.supp.CodeMappings.TerritoryCodes { + i := regionISO.index(tc.Type) + isoOffset + if d := m49map[i]; d != 0 { + log.Panicf("%s found as a duplicate UN.M49 code of %03d", tc.Numeric, d) + } + m49 := parseM49(tc.Numeric) + m49map[i] = m49 + if r := fromM49map[m49]; r == 0 { + fromM49map[m49] = i + } else if r != i { + dep := b.registry[regionISO.s[r-isoOffset]].deprecated + if t := b.registry[tc.Type]; t != nil && dep != "" && (t.deprecated == "" || t.deprecated > dep) { + fromM49map[m49] = i + } + } + } + for _, ta := range b.supp.Metadata.Alias.TerritoryAlias { + if len(ta.Type) == 3 && ta.Type[0] <= '9' && len(ta.Replacement) == 2 { + from := parseM49(ta.Type) + if r := fromM49map[from]; r == 0 { + fromM49map[from] = regionISO.index(ta.Replacement) + isoOffset + } + } + } + for _, tc := range b.supp.CodeMappings.TerritoryCodes { + if len(tc.Alpha3) == 3 { + update(tc.Type, tc.Alpha3) + } + } + // This entries are not included in territoryCodes. Mostly 3-letter variants + // of deleted codes and an entry for QU. + for _, m := range []struct{ iso2, iso3 string }{ + {"CT", "CTE"}, + {"DY", "DHY"}, + {"HV", "HVO"}, + {"JT", "JTN"}, + {"MI", "MID"}, + {"NH", "NHB"}, + {"NQ", "ATN"}, + {"PC", "PCI"}, + {"PU", "PUS"}, + {"PZ", "PCZ"}, + {"RH", "RHO"}, + {"VD", "VDR"}, + {"WK", "WAK"}, + // These three-letter codes are used for others as well. + {"FQ", "ATF"}, + } { + update(m.iso2, m.iso3) + } + for i, s := range regionISO.s { + if len(s) != 4 { + regionISO.s[i] = s + " " + } + } + b.writeConst("regionISO", tag.Index(regionISO.join())) + b.writeConst("altRegionISO3", altRegionISO3) + b.writeSlice("altRegionIDs", altRegionIDs) + + // Create list of deprecated regions. + // TODO: consider inserting SF -> FI. Not included by CLDR, but is the only + // Transitionally-reserved mapping not included. + regionOldMap := stringSet{} + // Include regions in territoryAlias (not all are in the IANA registry!) + for _, reg := range b.supp.Metadata.Alias.TerritoryAlias { + if len(reg.Type) == 2 && reg.Reason == "deprecated" && len(reg.Replacement) == 2 { + regionOldMap.add(reg.Type) + regionOldMap.updateLater(reg.Type, reg.Replacement) + i, _ := regionISO.find(reg.Type) + j, _ := regionISO.find(reg.Replacement) + if k := m49map[i+isoOffset]; k == 0 { + m49map[i+isoOffset] = m49map[j+isoOffset] + } + } + } + b.writeSortedMap("regionOldMap", ®ionOldMap, func(s string) uint16 { + return uint16(b.region.index(s)) + }) + // 3-digit region lookup, groupings. + for i := 1; i < isoOffset; i++ { + m := parseM49(b.region.s[i]) + m49map[i] = m + fromM49map[m] = i + } + b.writeSlice("m49", m49map) + + const ( + searchBits = 7 + regionBits = 9 + ) + if len(m49map) >= 1< %d", len(m49map), 1<>searchBits] = int16(len(fromM49)) + } + b.writeSlice("m49Index", m49Index) + b.writeSlice("fromM49", fromM49) +} + +const ( + // TODO: put these lists in regionTypes as user data? Could be used for + // various optimizations and refinements and could be exposed in the API. + iso3166Except = "AC CP DG EA EU FX IC SU TA UK" + iso3166Trans = "AN BU CS NT TP YU ZR" // SF is not in our set of Regions. + // DY and RH are actually not deleted, but indeterminately reserved. + iso3166DelCLDR = "CT DD DY FQ HV JT MI NH NQ PC PU PZ RH VD WK YD" +) + +const ( + iso3166UserAssigned = 1 << iota + ccTLD + bcp47Region +) + +func find(list []string, s string) int { + for i, t := range list { + if t == s { + return i + } + } + return -1 +} + +// writeVariants generates per-variant information and creates a map from variant +// name to index value. We assign index values such that sorting multiple +// variants by index value will result in the correct order. +// There are two types of variants: specialized and general. Specialized variants +// are only applicable to certain language or language-script pairs. Generalized +// variants apply to any language. Generalized variants always sort after +// specialized variants. We will therefore always assign a higher index value +// to a generalized variant than any other variant. Generalized variants are +// sorted alphabetically among themselves. +// Specialized variants may also sort after other specialized variants. Such +// variants will be ordered after any of the variants they may follow. +// We assume that if a variant x is followed by a variant y, then for any prefix +// p of x, p-x is a prefix of y. This allows us to order tags based on the +// maximum of the length of any of its prefixes. +// TODO: it is possible to define a set of Prefix values on variants such that +// a total order cannot be defined to the point that this algorithm breaks. +// In other words, we cannot guarantee the same order of variants for the +// future using the same algorithm or for non-compliant combinations of +// variants. For this reason, consider using simple alphabetic sorting +// of variants and ignore Prefix restrictions altogether. +func (b *builder) writeVariant() { + generalized := stringSet{} + specialized := stringSet{} + specializedExtend := stringSet{} + // Collate the variants by type and check assumptions. + for _, v := range b.variant.slice() { + e := b.registry[v] + if len(e.prefix) == 0 { + generalized.add(v) + continue + } + c := strings.Split(e.prefix[0], "-") + hasScriptOrRegion := false + if len(c) > 1 { + _, hasScriptOrRegion = b.script.find(c[1]) + if !hasScriptOrRegion { + _, hasScriptOrRegion = b.region.find(c[1]) + + } + } + if len(c) == 1 || len(c) == 2 && hasScriptOrRegion { + // Variant is preceded by a language. + specialized.add(v) + continue + } + // Variant is preceded by another variant. + specializedExtend.add(v) + prefix := c[0] + "-" + if hasScriptOrRegion { + prefix += c[1] + } + for _, p := range e.prefix { + // Verify that the prefix minus the last element is a prefix of the + // predecessor element. + i := strings.LastIndex(p, "-") + pred := b.registry[p[i+1:]] + if find(pred.prefix, p[:i]) < 0 { + log.Fatalf("prefix %q for variant %q not consistent with predecessor spec", p, v) + } + // The sorting used below does not work in the general case. It works + // if we assume that variants that may be followed by others only have + // prefixes of the same length. Verify this. + count := strings.Count(p[:i], "-") + for _, q := range pred.prefix { + if c := strings.Count(q, "-"); c != count { + log.Fatalf("variant %q preceding %q has a prefix %q of size %d; want %d", p[i+1:], v, q, c, count) + } + } + if !strings.HasPrefix(p, prefix) { + log.Fatalf("prefix %q of variant %q should start with %q", p, v, prefix) + } + } + } + + // Sort extended variants. + a := specializedExtend.s + less := func(v, w string) bool { + // Sort by the maximum number of elements. + maxCount := func(s string) (max int) { + for _, p := range b.registry[s].prefix { + if c := strings.Count(p, "-"); c > max { + max = c + } + } + return + } + if cv, cw := maxCount(v), maxCount(w); cv != cw { + return cv < cw + } + // Sort by name as tie breaker. + return v < w + } + sort.Sort(funcSorter{less, sort.StringSlice(a)}) + specializedExtend.frozen = true + + // Create index from variant name to index. + variantIndex := make(map[string]uint8) + add := func(s []string) { + for _, v := range s { + variantIndex[v] = uint8(len(variantIndex)) + } + } + add(specialized.slice()) + add(specializedExtend.s) + numSpecialized := len(variantIndex) + add(generalized.slice()) + if n := len(variantIndex); n > 255 { + log.Fatalf("maximum number of variants exceeded: was %d; want <= 255", n) + } + b.writeMap("variantIndex", variantIndex) + b.writeConst("variantNumSpecialized", numSpecialized) +} + +func (b *builder) writeLanguageInfo() { +} + +// writeLikelyData writes tables that are used both for finding parent relations and for +// language matching. Each entry contains additional bits to indicate the status of the +// data to know when it cannot be used for parent relations. +func (b *builder) writeLikelyData() { + const ( + isList = 1 << iota + scriptInFrom + regionInFrom + ) + type ( // generated types + likelyScriptRegion struct { + region uint16 + script uint8 + flags uint8 + } + likelyLangScript struct { + lang uint16 + script uint8 + flags uint8 + } + likelyLangRegion struct { + lang uint16 + region uint16 + } + // likelyTag is used for getting likely tags for group regions, where + // the likely region might be a region contained in the group. + likelyTag struct { + lang uint16 + region uint16 + script uint8 + } + ) + var ( // generated variables + likelyRegionGroup = make([]likelyTag, len(b.groups)) + likelyLang = make([]likelyScriptRegion, len(b.lang.s)) + likelyRegion = make([]likelyLangScript, len(b.region.s)) + likelyScript = make([]likelyLangRegion, len(b.script.s)) + likelyLangList = []likelyScriptRegion{} + likelyRegionList = []likelyLangScript{} + ) + type fromTo struct { + from, to []string + } + langToOther := map[int][]fromTo{} + regionToOther := map[int][]fromTo{} + for _, m := range b.supp.LikelySubtags.LikelySubtag { + from := strings.Split(m.From, "_") + to := strings.Split(m.To, "_") + if len(to) != 3 { + log.Fatalf("invalid number of subtags in %q: found %d, want 3", m.To, len(to)) + } + if len(from) > 3 { + log.Fatalf("invalid number of subtags: found %d, want 1-3", len(from)) + } + if from[0] != to[0] && from[0] != "und" { + log.Fatalf("unexpected language change in expansion: %s -> %s", from, to) + } + if len(from) == 3 { + if from[2] != to[2] { + log.Fatalf("unexpected region change in expansion: %s -> %s", from, to) + } + if from[0] != "und" { + log.Fatalf("unexpected fully specified from tag: %s -> %s", from, to) + } + } + if len(from) == 1 || from[0] != "und" { + id := 0 + if from[0] != "und" { + id = b.lang.index(from[0]) + } + langToOther[id] = append(langToOther[id], fromTo{from, to}) + } else if len(from) == 2 && len(from[1]) == 4 { + sid := b.script.index(from[1]) + likelyScript[sid].lang = uint16(b.langIndex(to[0])) + likelyScript[sid].region = uint16(b.region.index(to[2])) + } else { + r := b.region.index(from[len(from)-1]) + if id, ok := b.groups[r]; ok { + if from[0] != "und" { + log.Fatalf("region changed unexpectedly: %s -> %s", from, to) + } + likelyRegionGroup[id].lang = uint16(b.langIndex(to[0])) + likelyRegionGroup[id].script = uint8(b.script.index(to[1])) + likelyRegionGroup[id].region = uint16(b.region.index(to[2])) + } else { + regionToOther[r] = append(regionToOther[r], fromTo{from, to}) + } + } + } + b.writeType(likelyLangRegion{}) + b.writeSlice("likelyScript", likelyScript) + + for id := range b.lang.s { + list := langToOther[id] + if len(list) == 1 { + likelyLang[id].region = uint16(b.region.index(list[0].to[2])) + likelyLang[id].script = uint8(b.script.index(list[0].to[1])) + } else if len(list) > 1 { + likelyLang[id].flags = isList + likelyLang[id].region = uint16(len(likelyLangList)) + likelyLang[id].script = uint8(len(list)) + for _, x := range list { + flags := uint8(0) + if len(x.from) > 1 { + if x.from[1] == x.to[2] { + flags = regionInFrom + } else { + flags = scriptInFrom + } + } + likelyLangList = append(likelyLangList, likelyScriptRegion{ + region: uint16(b.region.index(x.to[2])), + script: uint8(b.script.index(x.to[1])), + flags: flags, + }) + } + } + } + // TODO: merge suppressScript data with this table. + b.writeType(likelyScriptRegion{}) + b.writeSlice("likelyLang", likelyLang) + b.writeSlice("likelyLangList", likelyLangList) + + for id := range b.region.s { + list := regionToOther[id] + if len(list) == 1 { + likelyRegion[id].lang = uint16(b.langIndex(list[0].to[0])) + likelyRegion[id].script = uint8(b.script.index(list[0].to[1])) + if len(list[0].from) > 2 { + likelyRegion[id].flags = scriptInFrom + } + } else if len(list) > 1 { + likelyRegion[id].flags = isList + likelyRegion[id].lang = uint16(len(likelyRegionList)) + likelyRegion[id].script = uint8(len(list)) + for i, x := range list { + if len(x.from) == 2 && i != 0 || i > 0 && len(x.from) != 3 { + log.Fatalf("unspecified script must be first in list: %v at %d", x.from, i) + } + x := likelyLangScript{ + lang: uint16(b.langIndex(x.to[0])), + script: uint8(b.script.index(x.to[1])), + } + if len(list[0].from) > 2 { + x.flags = scriptInFrom + } + likelyRegionList = append(likelyRegionList, x) + } + } + } + b.writeType(likelyLangScript{}) + b.writeSlice("likelyRegion", likelyRegion) + b.writeSlice("likelyRegionList", likelyRegionList) + + b.writeType(likelyTag{}) + b.writeSlice("likelyRegionGroup", likelyRegionGroup) +} + +func (b *builder) writeRegionInclusionData() { + var ( + // mm holds for each group the set of groups with a distance of 1. + mm = make(map[int][]index) + + // containment holds for each group the transitive closure of + // containment of other groups. + containment = make(map[index][]index) + ) + for _, g := range b.supp.TerritoryContainment.Group { + // Skip UN and EURO zone as they are flattening the containment + // relationship. + if g.Type == "EZ" || g.Type == "UN" { + continue + } + group := b.region.index(g.Type) + groupIdx := b.groups[group] + for _, mem := range strings.Split(g.Contains, " ") { + r := b.region.index(mem) + mm[r] = append(mm[r], groupIdx) + if g, ok := b.groups[r]; ok { + mm[group] = append(mm[group], g) + containment[groupIdx] = append(containment[groupIdx], g) + } + } + } + + regionContainment := make([]uint64, len(b.groups)) + for _, g := range b.groups { + l := containment[g] + + // Compute the transitive closure of containment. + for i := 0; i < len(l); i++ { + l = append(l, containment[l[i]]...) + } + + // Compute the bitmask. + regionContainment[g] = 1 << g + for _, v := range l { + regionContainment[g] |= 1 << v + } + } + b.writeSlice("regionContainment", regionContainment) + + regionInclusion := make([]uint8, len(b.region.s)) + bvs := make(map[uint64]index) + // Make the first bitvector positions correspond with the groups. + for r, i := range b.groups { + bv := uint64(1 << i) + for _, g := range mm[r] { + bv |= 1 << g + } + bvs[bv] = i + regionInclusion[r] = uint8(bvs[bv]) + } + for r := 1; r < len(b.region.s); r++ { + if _, ok := b.groups[r]; !ok { + bv := uint64(0) + for _, g := range mm[r] { + bv |= 1 << g + } + if bv == 0 { + // Pick the world for unspecified regions. + bv = 1 << b.groups[b.region.index("001")] + } + if _, ok := bvs[bv]; !ok { + bvs[bv] = index(len(bvs)) + } + regionInclusion[r] = uint8(bvs[bv]) + } + } + b.writeSlice("regionInclusion", regionInclusion) + regionInclusionBits := make([]uint64, len(bvs)) + for k, v := range bvs { + regionInclusionBits[v] = uint64(k) + } + // Add bit vectors for increasingly large distances until a fixed point is reached. + regionInclusionNext := []uint8{} + for i := 0; i < len(regionInclusionBits); i++ { + bits := regionInclusionBits[i] + next := bits + for i := uint(0); i < uint(len(b.groups)); i++ { + if bits&(1< 6 { + log.Fatalf("Too many groups: %d", i) + } + idToIndex[mv.Id] = uint8(i + 1) + // TODO: also handle '-' + for _, r := range strings.Split(mv.Value, "+") { + todo := []string{r} + for k := 0; k < len(todo); k++ { + r := todo[k] + regionToGroups[b.regionIndex(r)] |= 1 << uint8(i) + todo = append(todo, regionHierarchy[r]...) + } + } + } + b.w.WriteVar("regionToGroups", regionToGroups) + + // maps language id to in- and out-of-group region. + paradigmLocales := [][3]uint16{} + locales := strings.Split(lm[0].ParadigmLocales[0].Locales, " ") + for i := 0; i < len(locales); i += 2 { + x := [3]uint16{} + for j := 0; j < 2; j++ { + pc := strings.SplitN(locales[i+j], "-", 2) + x[0] = b.langIndex(pc[0]) + if len(pc) == 2 { + x[1+j] = uint16(b.regionIndex(pc[1])) + } + } + paradigmLocales = append(paradigmLocales, x) + } + b.w.WriteVar("paradigmLocales", paradigmLocales) + + b.w.WriteType(mutualIntelligibility{}) + b.w.WriteType(scriptIntelligibility{}) + b.w.WriteType(regionIntelligibility{}) + + matchLang := []mutualIntelligibility{} + matchScript := []scriptIntelligibility{} + matchRegion := []regionIntelligibility{} + // Convert the languageMatch entries in lists keyed by desired language. + for _, m := range lm[0].LanguageMatch { + // Different versions of CLDR use different separators. + desired := strings.Replace(m.Desired, "-", "_", -1) + supported := strings.Replace(m.Supported, "-", "_", -1) + d := strings.Split(desired, "_") + s := strings.Split(supported, "_") + if len(d) != len(s) { + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + continue + } + distance, _ := strconv.ParseInt(m.Distance, 10, 8) + switch len(d) { + case 2: + if desired == supported && desired == "*_*" { + continue + } + // language-script pair. + matchScript = append(matchScript, scriptIntelligibility{ + wantLang: uint16(b.langIndex(d[0])), + haveLang: uint16(b.langIndex(s[0])), + wantScript: uint8(b.scriptIndex(d[1])), + haveScript: uint8(b.scriptIndex(s[1])), + distance: uint8(distance), + }) + if m.Oneway != "true" { + matchScript = append(matchScript, scriptIntelligibility{ + wantLang: uint16(b.langIndex(s[0])), + haveLang: uint16(b.langIndex(d[0])), + wantScript: uint8(b.scriptIndex(s[1])), + haveScript: uint8(b.scriptIndex(d[1])), + distance: uint8(distance), + }) + } + case 1: + if desired == supported && desired == "*" { + continue + } + if distance == 1 { + // nb == no is already handled by macro mapping. Check there + // really is only this case. + if d[0] != "no" || s[0] != "nb" { + log.Fatalf("unhandled equivalence %s == %s", s[0], d[0]) + } + continue + } + // TODO: consider dropping oneway field and just doubling the entry. + matchLang = append(matchLang, mutualIntelligibility{ + want: uint16(b.langIndex(d[0])), + have: uint16(b.langIndex(s[0])), + distance: uint8(distance), + oneway: m.Oneway == "true", + }) + case 3: + if desired == supported && desired == "*_*_*" { + continue + } + if desired != supported { + // This is now supported by CLDR, but only one case, which + // should already be covered by paradigm locales. For instance, + // test case "und, en, en-GU, en-IN, en-GB ; en-ZA ; en-GB" in + // testdata/CLDRLocaleMatcherTest.txt tests this. + if supported != "en_*_GB" { + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + } + continue + } + ri := regionIntelligibility{ + lang: b.langIndex(d[0]), + distance: uint8(distance), + } + if d[1] != "*" { + ri.script = uint8(b.scriptIndex(d[1])) + } + switch { + case d[2] == "*": + ri.group = 0x80 // not contained in anything + case strings.HasPrefix(d[2], "$!"): + ri.group = 0x80 + d[2] = "$" + d[2][len("$!"):] + fallthrough + case strings.HasPrefix(d[2], "$"): + ri.group |= idToIndex[d[2]] + } + matchRegion = append(matchRegion, ri) + default: + log.Fatalf("not supported: desired=%q; supported=%q", desired, supported) + } + } + sort.SliceStable(matchLang, func(i, j int) bool { + return matchLang[i].distance < matchLang[j].distance + }) + b.w.WriteComment(` + matchLang holds pairs of langIDs of base languages that are typically + mutually intelligible. Each pair is associated with a confidence and + whether the intelligibility goes one or both ways.`) + b.w.WriteVar("matchLang", matchLang) + + b.w.WriteComment(` + matchScript holds pairs of scriptIDs where readers of one script + can typically also read the other. Each is associated with a confidence.`) + sort.SliceStable(matchScript, func(i, j int) bool { + return matchScript[i].distance < matchScript[j].distance + }) + b.w.WriteVar("matchScript", matchScript) + + sort.SliceStable(matchRegion, func(i, j int) bool { + return matchRegion[i].distance < matchRegion[j].distance + }) + b.w.WriteVar("matchRegion", matchRegion) +} diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go new file mode 100644 index 000000000..30a3aa933 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/norm/maketables.go @@ -0,0 +1,986 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Normalization table generator. +// Data read from the web. +// See forminfo.go for a description of the trie values associated with each rune. + +package main + +import ( + "bytes" + "encoding/binary" + "flag" + "fmt" + "io" + "log" + "sort" + "strconv" + "strings" + + "golang.org/x/text/internal/gen" + "golang.org/x/text/internal/triegen" + "golang.org/x/text/internal/ucd" +) + +func main() { + gen.Init() + loadUnicodeData() + compactCCC() + loadCompositionExclusions() + completeCharFields(FCanonical) + completeCharFields(FCompatibility) + computeNonStarterCounts() + verifyComputed() + printChars() + testDerived() + printTestdata() + makeTables() +} + +var ( + tablelist = flag.String("tables", + "all", + "comma-separated list of which tables to generate; "+ + "can be 'decomp', 'recomp', 'info' and 'all'") + test = flag.Bool("test", + false, + "test existing tables against DerivedNormalizationProps and generate test data for regression testing") + verbose = flag.Bool("verbose", + false, + "write data to stdout as it is parsed") +) + +const MaxChar = 0x10FFFF // anything above this shouldn't exist + +// Quick Check properties of runes allow us to quickly +// determine whether a rune may occur in a normal form. +// For a given normal form, a rune may be guaranteed to occur +// verbatim (QC=Yes), may or may not combine with another +// rune (QC=Maybe), or may not occur (QC=No). +type QCResult int + +const ( + QCUnknown QCResult = iota + QCYes + QCNo + QCMaybe +) + +func (r QCResult) String() string { + switch r { + case QCYes: + return "Yes" + case QCNo: + return "No" + case QCMaybe: + return "Maybe" + } + return "***UNKNOWN***" +} + +const ( + FCanonical = iota // NFC or NFD + FCompatibility // NFKC or NFKD + FNumberOfFormTypes +) + +const ( + MComposed = iota // NFC or NFKC + MDecomposed // NFD or NFKD + MNumberOfModes +) + +// This contains only the properties we're interested in. +type Char struct { + name string + codePoint rune // if zero, this index is not a valid code point. + ccc uint8 // canonical combining class + origCCC uint8 + excludeInComp bool // from CompositionExclusions.txt + compatDecomp bool // it has a compatibility expansion + + nTrailingNonStarters uint8 + nLeadingNonStarters uint8 // must be equal to trailing if non-zero + + forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility + + state State +} + +var chars = make([]Char, MaxChar+1) +var cccMap = make(map[uint8]uint8) + +func (c Char) String() string { + buf := new(bytes.Buffer) + + fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name) + fmt.Fprintf(buf, " ccc: %v\n", c.ccc) + fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp) + fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp) + fmt.Fprintf(buf, " state: %v\n", c.state) + fmt.Fprintf(buf, " NFC:\n") + fmt.Fprint(buf, c.forms[FCanonical]) + fmt.Fprintf(buf, " NFKC:\n") + fmt.Fprint(buf, c.forms[FCompatibility]) + + return buf.String() +} + +// In UnicodeData.txt, some ranges are marked like this: +// 3400;;Lo;0;L;;;;;N;;;;; +// 4DB5;;Lo;0;L;;;;;N;;;;; +// parseCharacter keeps a state variable indicating the weirdness. +type State int + +const ( + SNormal State = iota // known to be zero for the type + SFirst + SLast + SMissing +) + +var lastChar = rune('\u0000') + +func (c Char) isValid() bool { + return c.codePoint != 0 && c.state != SMissing +} + +type FormInfo struct { + quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed + verified [MNumberOfModes]bool // index: MComposed or MDecomposed + + combinesForward bool // May combine with rune on the right + combinesBackward bool // May combine with rune on the left + isOneWay bool // Never appears in result + inDecomp bool // Some decompositions result in this char. + decomp Decomposition + expandedDecomp Decomposition +} + +func (f FormInfo) String() string { + buf := bytes.NewBuffer(make([]byte, 0)) + + fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed]) + fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed]) + fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward) + fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward) + fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay) + fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp) + fmt.Fprintf(buf, " decomposition: %X\n", f.decomp) + fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp) + + return buf.String() +} + +type Decomposition []rune + +func parseDecomposition(s string, skipfirst bool) (a []rune, err error) { + decomp := strings.Split(s, " ") + if len(decomp) > 0 && skipfirst { + decomp = decomp[1:] + } + for _, d := range decomp { + point, err := strconv.ParseUint(d, 16, 64) + if err != nil { + return a, err + } + a = append(a, rune(point)) + } + return a, nil +} + +func loadUnicodeData() { + f := gen.OpenUCDFile("UnicodeData.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + r := p.Rune(ucd.CodePoint) + char := &chars[r] + + char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass)) + decmap := p.String(ucd.DecompMapping) + + exp, err := parseDecomposition(decmap, false) + isCompat := false + if err != nil { + if len(decmap) > 0 { + exp, err = parseDecomposition(decmap, true) + if err != nil { + log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err) + } + isCompat = true + } + } + + char.name = p.String(ucd.Name) + char.codePoint = r + char.forms[FCompatibility].decomp = exp + if !isCompat { + char.forms[FCanonical].decomp = exp + } else { + char.compatDecomp = true + } + if len(decmap) > 0 { + char.forms[FCompatibility].decomp = exp + } + } + if err := p.Err(); err != nil { + log.Fatal(err) + } +} + +// compactCCC converts the sparse set of CCC values to a continguous one, +// reducing the number of bits needed from 8 to 6. +func compactCCC() { + m := make(map[uint8]uint8) + for i := range chars { + c := &chars[i] + m[c.ccc] = 0 + } + cccs := []int{} + for v, _ := range m { + cccs = append(cccs, int(v)) + } + sort.Ints(cccs) + for i, c := range cccs { + cccMap[uint8(i)] = uint8(c) + m[uint8(c)] = uint8(i) + } + for i := range chars { + c := &chars[i] + c.origCCC = c.ccc + c.ccc = m[c.ccc] + } + if len(m) >= 1<<6 { + log.Fatalf("too many difference CCC values: %d >= 64", len(m)) + } +} + +// CompositionExclusions.txt has form: +// 0958 # ... +// See https://unicode.org/reports/tr44/ for full explanation +func loadCompositionExclusions() { + f := gen.OpenUCDFile("CompositionExclusions.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + c := &chars[p.Rune(0)] + if c.excludeInComp { + log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint) + } + c.excludeInComp = true + } + if e := p.Err(); e != nil { + log.Fatal(e) + } +} + +// hasCompatDecomp returns true if any of the recursive +// decompositions contains a compatibility expansion. +// In this case, the character may not occur in NFK*. +func hasCompatDecomp(r rune) bool { + c := &chars[r] + if c.compatDecomp { + return true + } + for _, d := range c.forms[FCompatibility].decomp { + if hasCompatDecomp(d) { + return true + } + } + return false +} + +// Hangul related constants. +const ( + HangulBase = 0xAC00 + HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28) + + JamoLBase = 0x1100 + JamoLEnd = 0x1113 + JamoVBase = 0x1161 + JamoVEnd = 0x1176 + JamoTBase = 0x11A8 + JamoTEnd = 0x11C3 + + JamoLVTCount = 19 * 21 * 28 + JamoTCount = 28 +) + +func isHangul(r rune) bool { + return HangulBase <= r && r < HangulEnd +} + +func isHangulWithoutJamoT(r rune) bool { + if !isHangul(r) { + return false + } + r -= HangulBase + return r < JamoLVTCount && r%JamoTCount == 0 +} + +func ccc(r rune) uint8 { + return chars[r].ccc +} + +// Insert a rune in a buffer, ordered by Canonical Combining Class. +func insertOrdered(b Decomposition, r rune) Decomposition { + n := len(b) + b = append(b, 0) + cc := ccc(r) + if cc > 0 { + // Use bubble sort. + for ; n > 0; n-- { + if ccc(b[n-1]) <= cc { + break + } + b[n] = b[n-1] + } + } + b[n] = r + return b +} + +// Recursively decompose. +func decomposeRecursive(form int, r rune, d Decomposition) Decomposition { + dcomp := chars[r].forms[form].decomp + if len(dcomp) == 0 { + return insertOrdered(d, r) + } + for _, c := range dcomp { + d = decomposeRecursive(form, c, d) + } + return d +} + +func completeCharFields(form int) { + // Phase 0: pre-expand decomposition. + for i := range chars { + f := &chars[i].forms[form] + if len(f.decomp) == 0 { + continue + } + exp := make(Decomposition, 0) + for _, c := range f.decomp { + exp = decomposeRecursive(form, c, exp) + } + f.expandedDecomp = exp + } + + // Phase 1: composition exclusion, mark decomposition. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + // Marks script-specific exclusions and version restricted. + f.isOneWay = c.excludeInComp + + // Singletons + f.isOneWay = f.isOneWay || len(f.decomp) == 1 + + // Non-starter decompositions + if len(f.decomp) > 1 { + chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0 + f.isOneWay = f.isOneWay || chk + } + + // Runes that decompose into more than two runes. + f.isOneWay = f.isOneWay || len(f.decomp) > 2 + + if form == FCompatibility { + f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint) + } + + for _, r := range f.decomp { + chars[r].forms[form].inDecomp = true + } + } + + // Phase 2: forward and backward combining. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + if !f.isOneWay && len(f.decomp) == 2 { + f0 := &chars[f.decomp[0]].forms[form] + f1 := &chars[f.decomp[1]].forms[form] + if !f0.isOneWay { + f0.combinesForward = true + } + if !f1.isOneWay { + f1.combinesBackward = true + } + } + if isHangulWithoutJamoT(rune(i)) { + f.combinesForward = true + } + } + + // Phase 3: quick check values. + for i := range chars { + c := &chars[i] + f := &c.forms[form] + + switch { + case len(f.decomp) > 0: + f.quickCheck[MDecomposed] = QCNo + case isHangul(rune(i)): + f.quickCheck[MDecomposed] = QCNo + default: + f.quickCheck[MDecomposed] = QCYes + } + switch { + case f.isOneWay: + f.quickCheck[MComposed] = QCNo + case (i & 0xffff00) == JamoLBase: + f.quickCheck[MComposed] = QCYes + if JamoLBase <= i && i < JamoLEnd { + f.combinesForward = true + } + if JamoVBase <= i && i < JamoVEnd { + f.quickCheck[MComposed] = QCMaybe + f.combinesBackward = true + f.combinesForward = true + } + if JamoTBase <= i && i < JamoTEnd { + f.quickCheck[MComposed] = QCMaybe + f.combinesBackward = true + } + case !f.combinesBackward: + f.quickCheck[MComposed] = QCYes + default: + f.quickCheck[MComposed] = QCMaybe + } + } +} + +func computeNonStarterCounts() { + // Phase 4: leading and trailing non-starter count + for i := range chars { + c := &chars[i] + + runes := []rune{rune(i)} + // We always use FCompatibility so that the CGJ insertion points do not + // change for repeated normalizations with different forms. + if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 { + runes = exp + } + // We consider runes that combine backwards to be non-starters for the + // purpose of Stream-Safe Text Processing. + for _, r := range runes { + if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { + break + } + c.nLeadingNonStarters++ + } + for i := len(runes) - 1; i >= 0; i-- { + if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward { + break + } + c.nTrailingNonStarters++ + } + if c.nTrailingNonStarters > 3 { + log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes) + } + + if isHangul(rune(i)) { + c.nTrailingNonStarters = 2 + if isHangulWithoutJamoT(rune(i)) { + c.nTrailingNonStarters = 1 + } + } + + if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t { + log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t) + } + if t := c.nTrailingNonStarters; t > 3 { + log.Fatalf("%U: number of trailing non-starters is %d > 3", t) + } + } +} + +func printBytes(w io.Writer, b []byte, name string) { + fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b)) + fmt.Fprintf(w, "var %s = [...]byte {", name) + for i, c := range b { + switch { + case i%64 == 0: + fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63) + case i%8 == 0: + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "0x%.2X, ", c) + } + fmt.Fprint(w, "\n}\n\n") +} + +// See forminfo.go for format. +func makeEntry(f *FormInfo, c *Char) uint16 { + e := uint16(0) + if r := c.codePoint; HangulBase <= r && r < HangulEnd { + e |= 0x40 + } + if f.combinesForward { + e |= 0x20 + } + if f.quickCheck[MDecomposed] == QCNo { + e |= 0x4 + } + switch f.quickCheck[MComposed] { + case QCYes: + case QCNo: + e |= 0x10 + case QCMaybe: + e |= 0x18 + default: + log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed]) + } + e |= uint16(c.nTrailingNonStarters) + return e +} + +// decompSet keeps track of unique decompositions, grouped by whether +// the decomposition is followed by a trailing and/or leading CCC. +type decompSet [7]map[string]bool + +const ( + normalDecomp = iota + firstMulti + firstCCC + endMulti + firstLeadingCCC + firstCCCZeroExcept + firstStarterWithNLead + lastDecomp +) + +var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"} + +func makeDecompSet() decompSet { + m := decompSet{} + for i := range m { + m[i] = make(map[string]bool) + } + return m +} +func (m *decompSet) insert(key int, s string) { + m[key][s] = true +} + +func printCharInfoTables(w io.Writer) int { + mkstr := func(r rune, f *FormInfo) (int, string) { + d := f.expandedDecomp + s := string([]rune(d)) + if max := 1 << 6; len(s) >= max { + const msg = "%U: too many bytes in decomposition: %d >= %d" + log.Fatalf(msg, r, len(s), max) + } + head := uint8(len(s)) + if f.quickCheck[MComposed] != QCYes { + head |= 0x40 + } + if f.combinesForward { + head |= 0x80 + } + s = string([]byte{head}) + s + + lccc := ccc(d[0]) + tccc := ccc(d[len(d)-1]) + cc := ccc(r) + if cc != 0 && lccc == 0 && tccc == 0 { + log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc) + } + if tccc < lccc && lccc != 0 { + const msg = "%U: lccc (%d) must be <= tcc (%d)" + log.Fatalf(msg, r, lccc, tccc) + } + index := normalDecomp + nTrail := chars[r].nTrailingNonStarters + nLead := chars[r].nLeadingNonStarters + if tccc > 0 || lccc > 0 || nTrail > 0 { + tccc <<= 2 + tccc |= nTrail + s += string([]byte{tccc}) + index = endMulti + for _, r := range d[1:] { + if ccc(r) == 0 { + index = firstCCC + } + } + if lccc > 0 || nLead > 0 { + s += string([]byte{lccc}) + if index == firstCCC { + log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r) + } + index = firstLeadingCCC + } + if cc != lccc { + if cc != 0 { + log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc) + } + index = firstCCCZeroExcept + } + } else if len(d) > 1 { + index = firstMulti + } + return index, s + } + + decompSet := makeDecompSet() + const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail. + decompSet.insert(firstStarterWithNLead, nLeadStr) + + // Store the uniqued decompositions in a byte buffer, + // preceded by their byte length. + for _, c := range chars { + for _, f := range c.forms { + if len(f.expandedDecomp) == 0 { + continue + } + if f.combinesBackward { + log.Fatalf("%U: combinesBackward and decompose", c.codePoint) + } + index, s := mkstr(c.codePoint, &f) + decompSet.insert(index, s) + } + } + + decompositions := bytes.NewBuffer(make([]byte, 0, 10000)) + size := 0 + positionMap := make(map[string]uint16) + decompositions.WriteString("\000") + fmt.Fprintln(w, "const (") + for i, m := range decompSet { + sa := []string{} + for s := range m { + sa = append(sa, s) + } + sort.Strings(sa) + for _, s := range sa { + p := decompositions.Len() + decompositions.WriteString(s) + positionMap[s] = uint16(p) + } + if cname[i] != "" { + fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len()) + } + } + fmt.Fprintln(w, "maxDecomp = 0x8000") + fmt.Fprintln(w, ")") + b := decompositions.Bytes() + printBytes(w, b, "decomps") + size += len(b) + + varnames := []string{"nfc", "nfkc"} + for i := 0; i < FNumberOfFormTypes; i++ { + trie := triegen.NewTrie(varnames[i]) + + for r, c := range chars { + f := c.forms[i] + d := f.expandedDecomp + if len(d) != 0 { + _, key := mkstr(c.codePoint, &f) + trie.Insert(rune(r), uint64(positionMap[key])) + if c.ccc != ccc(d[0]) { + // We assume the lead ccc of a decomposition !=0 in this case. + if ccc(d[0]) == 0 { + log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc) + } + } + } else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward { + // Handle cases where it can't be detected that the nLead should be equal + // to nTrail. + trie.Insert(c.codePoint, uint64(positionMap[nLeadStr])) + } else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 { + trie.Insert(c.codePoint, uint64(0x8000|v)) + } + } + sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]})) + if err != nil { + log.Fatal(err) + } + size += sz + } + return size +} + +func contains(sa []string, s string) bool { + for _, a := range sa { + if a == s { + return true + } + } + return false +} + +func makeTables() { + w := &bytes.Buffer{} + + size := 0 + if *tablelist == "" { + return + } + list := strings.Split(*tablelist, ",") + if *tablelist == "all" { + list = []string{"recomp", "info"} + } + + // Compute maximum decomposition size. + max := 0 + for _, c := range chars { + if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max { + max = n + } + } + fmt.Fprintln(w, `import "sync"`) + fmt.Fprintln(w) + + fmt.Fprintln(w, "const (") + fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.") + fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion()) + fmt.Fprintln(w) + fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform") + fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at") + fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that") + fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.") + fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max) + fmt.Fprintln(w, ")\n") + + // Print the CCC remap table. + size += len(cccMap) + fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap)) + for i := 0; i < len(cccMap); i++ { + if i%8 == 0 { + fmt.Fprintln(w) + } + fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)]) + } + fmt.Fprintln(w, "\n}\n") + + if contains(list, "info") { + size += printCharInfoTables(w) + } + + if contains(list, "recomp") { + // Note that we use 32 bit keys, instead of 64 bit. + // This clips the bits of three entries, but we know + // this won't cause a collision. The compiler will catch + // any changes made to UnicodeData.txt that introduces + // a collision. + // Note that the recomposition map for NFC and NFKC + // are identical. + + // Recomposition map + nrentries := 0 + for _, c := range chars { + f := c.forms[FCanonical] + if !f.isOneWay && len(f.decomp) > 0 { + nrentries++ + } + } + sz := nrentries * 8 + size += sz + fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz) + fmt.Fprintln(w, "var recompMap map[uint32]rune") + fmt.Fprintln(w, "var recompMapOnce sync.Once\n") + fmt.Fprintln(w, `const recompMapPacked = "" +`) + var buf [8]byte + for i, c := range chars { + f := c.forms[FCanonical] + d := f.decomp + if !f.isOneWay && len(d) > 0 { + key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1])) + binary.BigEndian.PutUint32(buf[:4], key) + binary.BigEndian.PutUint32(buf[4:], uint32(i)) + fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i)) + } + } + // hack so we don't have to special case the trailing plus sign + fmt.Fprintf(w, ` ""`) + fmt.Fprintln(w) + } + + fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size) + gen.WriteVersionedGoFile("tables.go", "norm", w.Bytes()) +} + +func printChars() { + if *verbose { + for _, c := range chars { + if !c.isValid() || c.state == SMissing { + continue + } + fmt.Println(c) + } + } +} + +// verifyComputed does various consistency tests. +func verifyComputed() { + for i, c := range chars { + for _, f := range c.forms { + isNo := (f.quickCheck[MDecomposed] == QCNo) + if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) { + log.Fatalf("%U: NF*D QC must be No if rune decomposes", i) + } + + isMaybe := f.quickCheck[MComposed] == QCMaybe + if f.combinesBackward != isMaybe { + log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i) + } + if len(f.decomp) > 0 && f.combinesForward && isMaybe { + log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i) + } + + if len(f.expandedDecomp) != 0 { + continue + } + if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b { + // We accept these runes to be treated differently (it only affects + // segment breaking in iteration, most likely on improper use), but + // reconsider if more characters are added. + // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; + // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; + // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; + // U+318E HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; + // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; + // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; + if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) { + log.Fatalf("%U: nLead was %v; want %v", i, a, b) + } + } + } + nfc := c.forms[FCanonical] + nfkc := c.forms[FCompatibility] + if nfc.combinesBackward != nfkc.combinesBackward { + log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint) + } + } +} + +// Use values in DerivedNormalizationProps.txt to compare against the +// values we computed. +// DerivedNormalizationProps.txt has form: +// 00C0..00C5 ; NFD_QC; N # ... +// 0374 ; NFD_QC; N # ... +// See https://unicode.org/reports/tr44/ for full explanation +func testDerived() { + f := gen.OpenUCDFile("DerivedNormalizationProps.txt") + defer f.Close() + p := ucd.New(f) + for p.Next() { + r := p.Rune(0) + c := &chars[r] + + var ftype, mode int + qt := p.String(1) + switch qt { + case "NFC_QC": + ftype, mode = FCanonical, MComposed + case "NFD_QC": + ftype, mode = FCanonical, MDecomposed + case "NFKC_QC": + ftype, mode = FCompatibility, MComposed + case "NFKD_QC": + ftype, mode = FCompatibility, MDecomposed + default: + continue + } + var qr QCResult + switch p.String(2) { + case "Y": + qr = QCYes + case "N": + qr = QCNo + case "M": + qr = QCMaybe + default: + log.Fatalf(`Unexpected quick check value "%s"`, p.String(2)) + } + if got := c.forms[ftype].quickCheck[mode]; got != qr { + log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr) + } + c.forms[ftype].verified[mode] = true + } + if err := p.Err(); err != nil { + log.Fatal(err) + } + // Any unspecified value must be QCYes. Verify this. + for i, c := range chars { + for j, fd := range c.forms { + for k, qr := range fd.quickCheck { + if !fd.verified[k] && qr != QCYes { + m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n" + log.Printf(m, i, j, k, qr, c.name) + } + } + } + } +} + +var testHeader = `const ( + Yes = iota + No + Maybe +) + +type formData struct { + qc uint8 + combinesForward bool + decomposition string +} + +type runeData struct { + r rune + ccc uint8 + nLead uint8 + nTrail uint8 + f [2]formData // 0: canonical; 1: compatibility +} + +func f(qc uint8, cf bool, dec string) [2]formData { + return [2]formData{{qc, cf, dec}, {qc, cf, dec}} +} + +func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData { + return [2]formData{{qc, cf, d}, {qck, cfk, dk}} +} + +var testData = []runeData{ +` + +func printTestdata() { + type lastInfo struct { + ccc uint8 + nLead uint8 + nTrail uint8 + f string + } + + last := lastInfo{} + w := &bytes.Buffer{} + fmt.Fprintf(w, testHeader) + for r, c := range chars { + f := c.forms[FCanonical] + qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) + f = c.forms[FCompatibility] + qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp) + s := "" + if d == dk && qc == qck && cf == cfk { + s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d) + } else { + s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk) + } + current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s} + if last != current { + fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s) + last = current + } + } + fmt.Fprintln(w, "}") + gen.WriteVersionedGoFile("data_test.go", "norm", w.Bytes()) +} diff --git a/vendor/golang.org/x/text/unicode/norm/triegen.go b/vendor/golang.org/x/text/unicode/norm/triegen.go new file mode 100644 index 000000000..45d711900 --- /dev/null +++ b/vendor/golang.org/x/text/unicode/norm/triegen.go @@ -0,0 +1,117 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// Trie table generator. +// Used by make*tables tools to generate a go file with trie data structures +// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte +// sequence are used to lookup offsets in the index table to be used for the +// next byte. The last byte is used to index into a table with 16-bit values. + +package main + +import ( + "fmt" + "io" +) + +const maxSparseEntries = 16 + +type normCompacter struct { + sparseBlocks [][]uint64 + sparseOffset []uint16 + sparseCount int + name string +} + +func mostFrequentStride(a []uint64) int { + counts := make(map[int]int) + var v int + for _, x := range a { + if stride := int(x) - v; v != 0 && stride >= 0 { + counts[stride]++ + } + v = int(x) + } + var maxs, maxc int + for stride, cnt := range counts { + if cnt > maxc || (cnt == maxc && stride < maxs) { + maxs, maxc = stride, cnt + } + } + return maxs +} + +func countSparseEntries(a []uint64) int { + stride := mostFrequentStride(a) + var v, count int + for _, tv := range a { + if int(tv)-v != stride { + if tv != 0 { + count++ + } + } + v = int(tv) + } + return count +} + +func (c *normCompacter) Size(v []uint64) (sz int, ok bool) { + if n := countSparseEntries(v); n <= maxSparseEntries { + return (n+1)*4 + 2, true + } + return 0, false +} + +func (c *normCompacter) Store(v []uint64) uint32 { + h := uint32(len(c.sparseOffset)) + c.sparseBlocks = append(c.sparseBlocks, v) + c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount)) + c.sparseCount += countSparseEntries(v) + 1 + return h +} + +func (c *normCompacter) Handler() string { + return c.name + "Sparse.lookup" +} + +func (c *normCompacter) Print(w io.Writer) (retErr error) { + p := func(f string, x ...interface{}) { + if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil { + retErr = err + } + } + + ls := len(c.sparseBlocks) + p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2) + p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset) + + ns := c.sparseCount + p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4) + p("var %sSparseValues = [%d]valueRange {", c.name, ns) + for i, b := range c.sparseBlocks { + p("\n// Block %#x, offset %#x", i, c.sparseOffset[i]) + var v int + stride := mostFrequentStride(b) + n := countSparseEntries(b) + p("\n{value:%#04x,lo:%#02x},", stride, uint8(n)) + for i, nv := range b { + if int(nv)-v != stride { + if v != 0 { + p(",hi:%#02x},", 0x80+i-1) + } + if nv != 0 { + p("\n{value:%#04x,lo:%#02x", nv, 0x80+i) + } + } + v = int(nv) + } + if v != 0 { + p(",hi:%#02x},", 0x80+len(b)-1) + } + } + p("\n}\n\n") + return +} diff --git a/vendor/gopkg.in/go-playground/validator.v9/README.md b/vendor/gopkg.in/go-playground/validator.v9/README.md index 8cb94d465..ba6a74e65 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/README.md +++ b/vendor/gopkg.in/go-playground/validator.v9/README.md @@ -1,7 +1,7 @@ Package validator ================ [![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-9.29.0-green.svg) +![Project status](https://img.shields.io/badge/version-9.29.1-green.svg) [![Build Status](https://semaphoreci.com/api/v1/joeybloggs/validator/branches/v9/badge.svg)](https://semaphoreci.com/joeybloggs/validator) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v9&service=github)](https://coveralls.io/github/go-playground/validator?branch=v9) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) diff --git a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go index a589ecc5f..338cddd75 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go +++ b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go @@ -1308,7 +1308,11 @@ func hasValue(fl FieldLevel) bool { func requireCheckFieldKind(fl FieldLevel, param string) bool { field := fl.Field() if len(param) > 0 { - field = fl.Parent().FieldByName(param) + if fl.Parent().Kind() == reflect.Ptr { + field = fl.Parent().Elem().FieldByName(param) + } else { + field = fl.Parent().FieldByName(param) + } } switch field.Kind() { case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: diff --git a/vendor/gopkg.in/go-playground/validator.v9/errors.go b/vendor/gopkg.in/go-playground/validator.v9/errors.go index 7dc0a358f..46c24c9b2 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/errors.go +++ b/vendor/gopkg.in/go-playground/validator.v9/errors.go @@ -152,8 +152,8 @@ type FieldError interface { // returns the FieldError's translated error // from the provided 'ut.Translator' and registered 'TranslationFunc' // - // NOTE: is not registered translation can be found it returns the same - // as calling fe.Error() + // NOTE: if no registered translator can be found it returns the same as + // calling fe.Error() Translate(ut ut.Translator) string } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3b91458e2..417988fd8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,5 +1,7 @@ -# github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2 => github.com/status-im/go-fcm v1.0.0-status +# github.com/NaySoftware/go-fcm v0.0.0-00010101000000-000000000000 => github.com/status-im/go-fcm v1.0.0-status github.com/NaySoftware/go-fcm +# github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 +github.com/StackExchange/wmi # github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 github.com/allegro/bigcache github.com/allegro/bigcache/queue @@ -7,7 +9,7 @@ github.com/allegro/bigcache/queue github.com/aristanetworks/goarista/monotime # github.com/beevik/ntp v0.2.0 github.com/beevik/ntp -# github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c +# github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 github.com/btcsuite/btcd/btcec github.com/btcsuite/btcd/chaincfg github.com/btcsuite/btcd/chaincfg/chainhash @@ -24,74 +26,92 @@ github.com/davecgh/go-spew/spew github.com/deckarep/golang-set # github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 github.com/edsrzf/mmap-go -# github.com/ethereum/go-ethereum v1.8.27 => github.com/status-im/go-ethereum v1.8.27-status.5 -github.com/ethereum/go-ethereum +# github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa +github.com/elastic/gosigar +github.com/elastic/gosigar/sys/windows +# github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.4 github.com/ethereum/go-ethereum/accounts -github.com/ethereum/go-ethereum/accounts/abi -github.com/ethereum/go-ethereum/accounts/abi/bind -github.com/ethereum/go-ethereum/accounts/abi/bind/backends github.com/ethereum/go-ethereum/accounts/keystore -github.com/ethereum/go-ethereum/accounts/usbwallet -github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor github.com/ethereum/go-ethereum/common -github.com/ethereum/go-ethereum/common/bitutil -github.com/ethereum/go-ethereum/common/fdlimit github.com/ethereum/go-ethereum/common/hexutil -github.com/ethereum/go-ethereum/common/math -github.com/ethereum/go-ethereum/common/mclock -github.com/ethereum/go-ethereum/common/prque -github.com/ethereum/go-ethereum/consensus -github.com/ethereum/go-ethereum/consensus/clique -github.com/ethereum/go-ethereum/consensus/ethash -github.com/ethereum/go-ethereum/consensus/misc -github.com/ethereum/go-ethereum/contracts/ens/contract -github.com/ethereum/go-ethereum/core -github.com/ethereum/go-ethereum/core/bloombits -github.com/ethereum/go-ethereum/core/rawdb -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/crypto -github.com/ethereum/go-ethereum/crypto/bn256 -github.com/ethereum/go-ethereum/crypto/bn256/cloudflare -github.com/ethereum/go-ethereum/crypto/bn256/google +github.com/ethereum/go-ethereum/ethclient +github.com/ethereum/go-ethereum/event +github.com/ethereum/go-ethereum/log +github.com/ethereum/go-ethereum/node +github.com/ethereum/go-ethereum/p2p/enode +github.com/ethereum/go-ethereum/p2p/discv5 +github.com/ethereum/go-ethereum/p2p +github.com/ethereum/go-ethereum/metrics +github.com/ethereum/go-ethereum +github.com/ethereum/go-ethereum/accounts/abi/bind +github.com/ethereum/go-ethereum/core/types +github.com/ethereum/go-ethereum/accounts/abi github.com/ethereum/go-ethereum/crypto/ecies -github.com/ethereum/go-ethereum/crypto/secp256k1 +github.com/ethereum/go-ethereum/p2p/enr +github.com/ethereum/go-ethereum/rlp +github.com/ethereum/go-ethereum/core github.com/ethereum/go-ethereum/eth github.com/ethereum/go-ethereum/eth/downloader -github.com/ethereum/go-ethereum/eth/fetcher +github.com/ethereum/go-ethereum/les +github.com/ethereum/go-ethereum/p2p/nat +github.com/ethereum/go-ethereum/params +github.com/ethereum/go-ethereum/common/mclock +github.com/ethereum/go-ethereum/rpc +github.com/ethereum/go-ethereum/ethapi github.com/ethereum/go-ethereum/eth/filters +github.com/ethereum/go-ethereum/consensus/ethash +github.com/ethereum/go-ethereum/common/math +github.com/ethereum/go-ethereum/crypto/secp256k1 +github.com/ethereum/go-ethereum/accounts/external +github.com/ethereum/go-ethereum/accounts/scwallet +github.com/ethereum/go-ethereum/accounts/usbwallet +github.com/ethereum/go-ethereum/core/rawdb +github.com/ethereum/go-ethereum/ethdb +github.com/ethereum/go-ethereum/internal/debug +github.com/ethereum/go-ethereum/p2p/netutil +github.com/ethereum/go-ethereum/common/bitutil +github.com/ethereum/go-ethereum/p2p/discover +github.com/ethereum/go-ethereum/trie +github.com/ethereum/go-ethereum/accounts/abi/bind/backends +github.com/ethereum/go-ethereum/common/prque +github.com/ethereum/go-ethereum/consensus +github.com/ethereum/go-ethereum/consensus/misc +github.com/ethereum/go-ethereum/core/state +github.com/ethereum/go-ethereum/core/vm +github.com/ethereum/go-ethereum/consensus/clique +github.com/ethereum/go-ethereum/core/bloombits +github.com/ethereum/go-ethereum/core/forkid +github.com/ethereum/go-ethereum/eth/fetcher github.com/ethereum/go-ethereum/eth/gasprice github.com/ethereum/go-ethereum/eth/tracers -github.com/ethereum/go-ethereum/eth/tracers/internal/tracers -github.com/ethereum/go-ethereum/ethapi -github.com/ethereum/go-ethereum/ethclient -github.com/ethereum/go-ethereum/ethdb -github.com/ethereum/go-ethereum/event -github.com/ethereum/go-ethereum/internal/debug github.com/ethereum/go-ethereum/internal/ethapi -github.com/ethereum/go-ethereum/les +github.com/ethereum/go-ethereum/miner +github.com/ethereum/go-ethereum/contracts/checkpointoracle +github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract github.com/ethereum/go-ethereum/les/flowcontrol github.com/ethereum/go-ethereum/light -github.com/ethereum/go-ethereum/log -github.com/ethereum/go-ethereum/metrics +github.com/ethereum/go-ethereum/signer/core +github.com/ethereum/go-ethereum/accounts/usbwallet/trezor +github.com/ethereum/go-ethereum/ethdb/leveldb +github.com/ethereum/go-ethereum/ethdb/memorydb github.com/ethereum/go-ethereum/metrics/exp -github.com/ethereum/go-ethereum/miner -github.com/ethereum/go-ethereum/node -github.com/ethereum/go-ethereum/p2p -github.com/ethereum/go-ethereum/p2p/discover -github.com/ethereum/go-ethereum/p2p/discv5 -github.com/ethereum/go-ethereum/p2p/enode -github.com/ethereum/go-ethereum/p2p/enr -github.com/ethereum/go-ethereum/p2p/nat -github.com/ethereum/go-ethereum/p2p/netutil -github.com/ethereum/go-ethereum/params -github.com/ethereum/go-ethereum/rlp -github.com/ethereum/go-ethereum/rpc -github.com/ethereum/go-ethereum/trie +github.com/ethereum/go-ethereum/crypto/blake2b +github.com/ethereum/go-ethereum/crypto/bn256 +github.com/ethereum/go-ethereum/eth/tracers/internal/tracers +github.com/ethereum/go-ethereum/common/fdlimit +github.com/ethereum/go-ethereum/signer/storage +github.com/ethereum/go-ethereum/metrics/prometheus +github.com/ethereum/go-ethereum/crypto/bn256/cloudflare +github.com/ethereum/go-ethereum/crypto/bn256/google # github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc -github.com/fjl/memsize github.com/fjl/memsize/memsizeui +github.com/fjl/memsize +# github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff +github.com/gballet/go-libpcsclite +# github.com/go-ole/go-ole v1.2.1 +github.com/go-ole/go-ole +github.com/go-ole/go-ole/oleutil # github.com/go-playground/locales v0.12.1 github.com/go-playground/locales github.com/go-playground/locales/currency @@ -99,14 +119,14 @@ github.com/go-playground/locales/currency github.com/go-playground/universal-translator # github.com/go-stack/stack v1.8.0 github.com/go-stack/stack -# github.com/gogo/protobuf v1.2.1 -github.com/gogo/protobuf/io +# github.com/gogo/protobuf v1.3.0 github.com/gogo/protobuf/proto +github.com/gogo/protobuf/io # github.com/golang-migrate/migrate/v4 v4.5.0 -github.com/golang-migrate/migrate/v4 -github.com/golang-migrate/migrate/v4/database github.com/golang-migrate/migrate/v4/source -# github.com/golang/mock v1.2.0 +github.com/golang-migrate/migrate/v4/database +github.com/golang-migrate/migrate/v4 +# github.com/golang/mock v1.3.1 github.com/golang/mock/gomock # github.com/golang/protobuf v1.3.2 github.com/golang/protobuf/proto @@ -115,7 +135,7 @@ github.com/golang/protobuf/protoc-gen-go/descriptor github.com/golang/snappy # github.com/google/uuid v1.1.1 github.com/google/uuid -# github.com/gorilla/websocket v1.4.0 +# github.com/gorilla/websocket v1.4.1 github.com/gorilla/websocket # github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/errwrap @@ -132,15 +152,15 @@ github.com/huin/goupnp/httpu github.com/huin/goupnp/scpd github.com/huin/goupnp/soap github.com/huin/goupnp/ssdp -# github.com/ipfs/go-cid v0.0.2 +# github.com/ipfs/go-cid v0.0.3 github.com/ipfs/go-cid # github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipfs-util # github.com/ipfs/go-log v0.0.1 github.com/ipfs/go-log github.com/ipfs/go-log/tracer -github.com/ipfs/go-log/tracer/wire github.com/ipfs/go-log/writer +github.com/ipfs/go-log/tracer/wire # github.com/jackpal/gateway v1.0.5 github.com/jackpal/gateway # github.com/jackpal/go-nat-pmp v1.0.1 @@ -154,58 +174,61 @@ github.com/jbenet/goprocess/periodic github.com/jbenet/goprocess/ratelimit # github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 github.com/jinzhu/copier -# github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2 -github.com/karalabe/hid +# github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 +github.com/karalabe/usb # github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b github.com/koron/go-ssdp # github.com/leodido/go-urn v1.1.0 github.com/leodido/go-urn -# github.com/lib/pq v1.0.0 +# github.com/lib/pq v1.2.0 github.com/lib/pq github.com/lib/pq/oid +github.com/lib/pq/scram # github.com/libp2p/go-addr-util v0.0.1 github.com/libp2p/go-addr-util # github.com/libp2p/go-buffer-pool v0.0.2 github.com/libp2p/go-buffer-pool # github.com/libp2p/go-conn-security-multistream v0.1.0 github.com/libp2p/go-conn-security-multistream +# github.com/libp2p/go-eventbus v0.1.0 +github.com/libp2p/go-eventbus # github.com/libp2p/go-flow-metrics v0.0.1 github.com/libp2p/go-flow-metrics -# github.com/libp2p/go-libp2p v0.1.1 +# github.com/libp2p/go-libp2p v0.4.0 github.com/libp2p/go-libp2p github.com/libp2p/go-libp2p/config github.com/libp2p/go-libp2p/p2p/host/basic github.com/libp2p/go-libp2p/p2p/host/relay github.com/libp2p/go-libp2p/p2p/host/routed github.com/libp2p/go-libp2p/p2p/protocol/identify -github.com/libp2p/go-libp2p/p2p/protocol/identify/pb github.com/libp2p/go-libp2p/p2p/protocol/ping +github.com/libp2p/go-libp2p/p2p/protocol/identify/pb # github.com/libp2p/go-libp2p-autonat v0.1.0 github.com/libp2p/go-libp2p-autonat github.com/libp2p/go-libp2p-autonat/pb -# github.com/libp2p/go-libp2p-circuit v0.1.0 +# github.com/libp2p/go-libp2p-circuit v0.1.3 github.com/libp2p/go-libp2p-circuit github.com/libp2p/go-libp2p-circuit/pb -# github.com/libp2p/go-libp2p-core v0.0.3 -github.com/libp2p/go-libp2p-core/connmgr +# github.com/libp2p/go-libp2p-core v0.2.3 github.com/libp2p/go-libp2p-core/crypto -github.com/libp2p/go-libp2p-core/crypto/pb -github.com/libp2p/go-libp2p-core/discovery github.com/libp2p/go-libp2p-core/helpers github.com/libp2p/go-libp2p-core/host -github.com/libp2p/go-libp2p-core/metrics -github.com/libp2p/go-libp2p-core/mux github.com/libp2p/go-libp2p-core/network github.com/libp2p/go-libp2p-core/peer +github.com/libp2p/go-libp2p-core/protocol +github.com/libp2p/go-libp2p-core/connmgr +github.com/libp2p/go-libp2p-core/metrics github.com/libp2p/go-libp2p-core/peerstore github.com/libp2p/go-libp2p-core/pnet -github.com/libp2p/go-libp2p-core/protocol -github.com/libp2p/go-libp2p-core/routing -github.com/libp2p/go-libp2p-core/sec -github.com/libp2p/go-libp2p-core/sec/insecure +github.com/libp2p/go-libp2p-core/crypto/pb +github.com/libp2p/go-libp2p-core/event +github.com/libp2p/go-libp2p-core/mux github.com/libp2p/go-libp2p-core/transport -# github.com/libp2p/go-libp2p-crypto v0.1.0 -github.com/libp2p/go-libp2p-crypto +github.com/libp2p/go-libp2p-core/sec +github.com/libp2p/go-libp2p-core/routing +github.com/libp2p/go-libp2p-core/sec/insecure +github.com/libp2p/go-libp2p-core/sec/insecure/pb +github.com/libp2p/go-libp2p-core/discovery # github.com/libp2p/go-libp2p-discovery v0.1.0 github.com/libp2p/go-libp2p-discovery # github.com/libp2p/go-libp2p-loggables v0.1.0 @@ -214,38 +237,39 @@ github.com/libp2p/go-libp2p-loggables github.com/libp2p/go-libp2p-mplex # github.com/libp2p/go-libp2p-nat v0.0.4 github.com/libp2p/go-libp2p-nat -# github.com/libp2p/go-libp2p-peer v0.2.0 -github.com/libp2p/go-libp2p-peer -# github.com/libp2p/go-libp2p-peerstore v0.1.0 +# github.com/libp2p/go-libp2p-peerstore v0.1.3 +github.com/libp2p/go-libp2p-peerstore/pstoremem github.com/libp2p/go-libp2p-peerstore github.com/libp2p/go-libp2p-peerstore/addr -github.com/libp2p/go-libp2p-peerstore/pstoremem -# github.com/libp2p/go-libp2p-secio v0.1.0 +# github.com/libp2p/go-libp2p-secio v0.2.0 github.com/libp2p/go-libp2p-secio github.com/libp2p/go-libp2p-secio/pb -# github.com/libp2p/go-libp2p-swarm v0.1.0 +# github.com/libp2p/go-libp2p-swarm v0.2.2 github.com/libp2p/go-libp2p-swarm # github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 github.com/libp2p/go-libp2p-transport-upgrader # github.com/libp2p/go-libp2p-yamux v0.2.1 github.com/libp2p/go-libp2p-yamux -# github.com/libp2p/go-maddr-filter v0.0.4 +# github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-maddr-filter # github.com/libp2p/go-mplex v0.1.0 github.com/libp2p/go-mplex -# github.com/libp2p/go-msgio v0.0.2 +# github.com/libp2p/go-msgio v0.0.4 github.com/libp2p/go-msgio # github.com/libp2p/go-nat v0.0.3 github.com/libp2p/go-nat +# github.com/libp2p/go-openssl v0.0.2 +github.com/libp2p/go-openssl +github.com/libp2p/go-openssl/utils # github.com/libp2p/go-reuseport v0.0.1 github.com/libp2p/go-reuseport # github.com/libp2p/go-reuseport-transport v0.0.2 github.com/libp2p/go-reuseport-transport # github.com/libp2p/go-stream-muxer-multistream v0.2.0 github.com/libp2p/go-stream-muxer-multistream -# github.com/libp2p/go-tcp-transport v0.1.0 +# github.com/libp2p/go-tcp-transport v0.1.1 github.com/libp2p/go-tcp-transport -# github.com/libp2p/go-ws-transport v0.1.0 +# github.com/libp2p/go-ws-transport v0.1.2 github.com/libp2p/go-ws-transport # github.com/libp2p/go-yamux v1.2.3 github.com/libp2p/go-yamux @@ -255,42 +279,46 @@ github.com/lucasb-eyer/go-colorful github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.5 github.com/mattn/go-isatty +# github.com/mattn/go-runewidth v0.0.3 +github.com/mattn/go-runewidth # github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/minio/blake2b-simd -# github.com/minio/sha256-simd v0.1.0 +# github.com/minio/sha256-simd v0.1.1 github.com/minio/sha256-simd # github.com/mr-tron/base58 v1.1.2 github.com/mr-tron/base58/base58 # github.com/multiformats/go-base32 v0.0.3 github.com/multiformats/go-base32 -# github.com/multiformats/go-multiaddr v0.0.4 +# github.com/multiformats/go-multiaddr v0.1.1 github.com/multiformats/go-multiaddr -# github.com/multiformats/go-multiaddr-dns v0.0.2 +# github.com/multiformats/go-multiaddr-dns v0.1.0 github.com/multiformats/go-multiaddr-dns -# github.com/multiformats/go-multiaddr-fmt v0.0.1 +# github.com/multiformats/go-multiaddr-fmt v0.1.0 github.com/multiformats/go-multiaddr-fmt -# github.com/multiformats/go-multiaddr-net v0.0.1 +# github.com/multiformats/go-multiaddr-net v0.1.0 github.com/multiformats/go-multiaddr-net # github.com/multiformats/go-multibase v0.0.1 github.com/multiformats/go-multibase -# github.com/multiformats/go-multihash v0.0.5 +# github.com/multiformats/go-multihash v0.0.8 github.com/multiformats/go-multihash # github.com/multiformats/go-multistream v0.1.0 github.com/multiformats/go-multistream # github.com/mutecomm/go-sqlcipher v0.0.0-20190227152316-55dbde17881f github.com/mutecomm/go-sqlcipher +# github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a +github.com/olekukonko/tablewriter # github.com/opentracing/opentracing-go v1.0.2 github.com/opentracing/opentracing-go github.com/opentracing/opentracing-go/ext github.com/opentracing/opentracing-go/log -# github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 +# github.com/pborman/uuid v1.2.0 github.com/pborman/uuid # github.com/pkg/errors v0.8.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib -# github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5 -github.com/prometheus/prometheus/util/flock +# github.com/prometheus/tsdb v0.10.0 +github.com/prometheus/tsdb/fileutil # github.com/rjeczalik/notify v0.9.1 github.com/rjeczalik/notify # github.com/rs/cors v1.6.0 @@ -299,9 +327,6 @@ github.com/rs/cors github.com/russolsen/transit # github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 github.com/shopspring/decimal -# github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a -github.com/spacemonkeygo/openssl -github.com/spacemonkeygo/openssl/utils # github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 github.com/spacemonkeygo/spacelog # github.com/spaolacci/murmur3 v1.1.0 @@ -310,65 +335,74 @@ github.com/spaolacci/murmur3 github.com/status-im/doubleratchet # github.com/status-im/go-multiaddr-ethv4 v1.2.0 github.com/status-im/go-multiaddr-ethv4 -# github.com/status-im/migrate/v4 v4.0.0-20190821140204-a9d340ec8fb76af4afda06acf01740d45d2661ed +# github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 +github.com/status-im/keycard-go/derivationpath +# github.com/status-im/migrate/v4 v4.3.1-status.0.20190822050738-a9d340ec8fb7 +github.com/status-im/migrate/v4/source/go_bindata github.com/status-im/migrate/v4 github.com/status-im/migrate/v4/database/postgres github.com/status-im/migrate/v4/database/sqlcipher -github.com/status-im/migrate/v4/source/go_bindata # github.com/status-im/rendezvous v1.3.0 github.com/status-im/rendezvous github.com/status-im/rendezvous/protocol github.com/status-im/rendezvous/server -# github.com/status-im/status-protocol-go v0.0.0-20190926081215-cc44ddb7ce44 +# github.com/status-im/status-protocol-go v0.2.3-0.20190926081215-cc44ddb7ce44 github.com/status-im/status-protocol-go -github.com/status-im/status-protocol-go/applicationmetadata -github.com/status-im/status-protocol-go/crypto +github.com/status-im/status-protocol-go/zaputil +github.com/status-im/status-protocol-go/encryption/multidevice +github.com/status-im/status-protocol-go/transport/whisper github.com/status-im/status-protocol-go/datasync github.com/status-im/status-protocol-go/datasync/peer github.com/status-im/status-protocol-go/encryption github.com/status-im/status-protocol-go/encryption/migrations -github.com/status-im/status-protocol-go/encryption/multidevice -github.com/status-im/status-protocol-go/encryption/publisher github.com/status-im/status-protocol-go/encryption/sharedsecret github.com/status-im/status-protocol-go/identity/alias github.com/status-im/status-protocol-go/identity/identicon github.com/status-im/status-protocol-go/migrations github.com/status-im/status-protocol-go/sqlite -github.com/status-im/status-protocol-go/transport/whisper github.com/status-im/status-protocol-go/transport/whisper/migrations github.com/status-im/status-protocol-go/v1 -github.com/status-im/status-protocol-go/zaputil +github.com/status-im/status-protocol-go/crypto +github.com/status-im/status-protocol-go/encryption/publisher +github.com/status-im/status-protocol-go/applicationmetadata # github.com/status-im/whisper v1.4.14 github.com/status-im/whisper/whisperv6 -# github.com/stretchr/testify v1.3.1-0.20190712000136-221dbe5ed467 -github.com/stretchr/testify/assert +# github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 +github.com/steakknife/bloomfilter +# github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 +github.com/steakknife/hamming +# github.com/stretchr/testify v1.4.0 github.com/stretchr/testify/require github.com/stretchr/testify/suite +github.com/stretchr/testify/assert # github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb/leveldb -github.com/syndtr/goleveldb/leveldb/cache -github.com/syndtr/goleveldb/leveldb/comparer github.com/syndtr/goleveldb/leveldb/errors -github.com/syndtr/goleveldb/leveldb/filter github.com/syndtr/goleveldb/leveldb/iterator -github.com/syndtr/goleveldb/leveldb/journal -github.com/syndtr/goleveldb/leveldb/memdb github.com/syndtr/goleveldb/leveldb/opt github.com/syndtr/goleveldb/leveldb/storage -github.com/syndtr/goleveldb/leveldb/table github.com/syndtr/goleveldb/leveldb/util +github.com/syndtr/goleveldb/leveldb/cache +github.com/syndtr/goleveldb/leveldb/comparer +github.com/syndtr/goleveldb/leveldb/filter +github.com/syndtr/goleveldb/leveldb/journal +github.com/syndtr/goleveldb/leveldb/memdb +github.com/syndtr/goleveldb/leveldb/table +# github.com/tyler-smith/go-bip39 v1.0.2 +github.com/tyler-smith/go-bip39 +github.com/tyler-smith/go-bip39/wordlists # github.com/vacp2p/mvds v0.0.21 github.com/vacp2p/mvds/node -github.com/vacp2p/mvds/node/migrations -github.com/vacp2p/mvds/peers -github.com/vacp2p/mvds/peers/migrations -github.com/vacp2p/mvds/persistenceutil github.com/vacp2p/mvds/protobuf github.com/vacp2p/mvds/state -github.com/vacp2p/mvds/state/migrations -github.com/vacp2p/mvds/store -github.com/vacp2p/mvds/store/migrations github.com/vacp2p/mvds/transport +github.com/vacp2p/mvds/persistenceutil +github.com/vacp2p/mvds/peers +github.com/vacp2p/mvds/store +github.com/vacp2p/mvds/node/migrations +github.com/vacp2p/mvds/peers/migrations +github.com/vacp2p/mvds/state/migrations +github.com/vacp2p/mvds/store/migrations # github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc github.com/whyrusleeping/go-logging # github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f @@ -377,65 +411,74 @@ github.com/whyrusleeping/go-notifier github.com/whyrusleeping/mafmt # github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/multiaddr-filter +# github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 +github.com/wsddn/go-ecdh +# go.opencensus.io v0.22.1 +go.opencensus.io/stats/view +go.opencensus.io/internal/tagencoding +go.opencensus.io/metric/metricdata +go.opencensus.io/metric/metricproducer +go.opencensus.io/stats +go.opencensus.io/stats/internal +go.opencensus.io/tag +go.opencensus.io/resource # go.uber.org/atomic v1.4.0 go.uber.org/atomic # go.uber.org/multierr v1.1.0 go.uber.org/multierr # go.uber.org/zap v1.10.0 go.uber.org/zap -go.uber.org/zap/buffer +go.uber.org/zap/zapcore go.uber.org/zap/internal/bufferpool +go.uber.org/zap/buffer go.uber.org/zap/internal/color go.uber.org/zap/internal/exit -go.uber.org/zap/zapcore -# golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 -golang.org/x/crypto/blake2s -golang.org/x/crypto/blowfish -golang.org/x/crypto/curve25519 -golang.org/x/crypto/ed25519 -golang.org/x/crypto/ed25519/internal/edwards25519 -golang.org/x/crypto/hkdf -golang.org/x/crypto/pbkdf2 -golang.org/x/crypto/ripemd160 -golang.org/x/crypto/scrypt +# golang.org/x/crypto v0.0.0-20191001141032-4663e185863a golang.org/x/crypto/sha3 golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.0.0-20190628185345-da137c7871d7 -golang.org/x/net/bpf +golang.org/x/crypto/hkdf +golang.org/x/crypto/pbkdf2 +golang.org/x/crypto/scrypt +golang.org/x/crypto/curve25519 +golang.org/x/crypto/ripemd160 +golang.org/x/crypto/blake2s +golang.org/x/crypto/ed25519 +golang.org/x/crypto/ed25519/internal/edwards25519 +# golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 golang.org/x/net/context -golang.org/x/net/html -golang.org/x/net/html/atom +golang.org/x/net/ipv4 golang.org/x/net/html/charset +golang.org/x/net/bpf golang.org/x/net/internal/iana golang.org/x/net/internal/socket -golang.org/x/net/ipv4 -golang.org/x/net/websocket -# golang.org/x/sync v0.0.0-20190423024810-112230192c58 +golang.org/x/net/html +golang.org/x/net/html/atom +# golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sync/syncmap -# golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 +# golang.org/x/sys v0.0.0-20190927073244-c990c680b611 golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 +golang.org/x/text/unicode/norm +golang.org/x/text/transform golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex -golang.org/x/text/encoding/internal golang.org/x/text/encoding/internal/identifier +golang.org/x/text/encoding/internal golang.org/x/text/encoding/japanese golang.org/x/text/encoding/korean golang.org/x/text/encoding/simplifiedchinese golang.org/x/text/encoding/traditionalchinese golang.org/x/text/encoding/unicode +golang.org/x/text/language +golang.org/x/text/internal/utf8internal +golang.org/x/text/runes golang.org/x/text/internal/language golang.org/x/text/internal/language/compact golang.org/x/text/internal/tag -golang.org/x/text/internal/utf8internal -golang.org/x/text/language -golang.org/x/text/runes -golang.org/x/text/transform -golang.org/x/text/unicode/norm -# gopkg.in/go-playground/validator.v9 v9.29.0 +# gopkg.in/go-playground/validator.v9 v9.29.1 gopkg.in/go-playground/validator.v9 # gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2